? diffs
Index: ChangeLog
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/ChangeLog,v
retrieving revision 1.141
diff -u -r1.141 ChangeLog
--- ChangeLog	26 Apr 2006 19:09:31 -0000	1.141
+++ ChangeLog	30 Apr 2006 16:54:55 -0000
@@ -1,3 +1,56 @@
+2006-04-30  Jost Boekemeier  <jostb@intern>
+
+	* PROTOCOL.TXT: Keep-alive added.
+
+	* client.c (handle_request, try_connect_to_server): Persistent
+	connections.
+	(clone_cfg, destroy_cloned_cfg): New from java.c
+
+	* java.c (clone_cfg, destroy_cloned_cfg): Moved to client.c
+	(OnIniPersistentConnections): New procedure
+	(RSHUTDOWN_FUNCTION): moved connection handling to client/protocol.
+	(MINFO): Display java.persistent_connections option.
+	(MSHUTDOWN_FUNCTION): close persistent, if necessary
+	
+	* init_cfg.c.in (option_set_by_user, init_cfg): Persistent connections.
+
+	* protocol.c (end): Changed incorrect assert()
+	(end_session): Removed incorrect assert.
+	(protocol_end): reset state for close persistent
+	(EndConnection): New method
+	(close_connection, recycle_connection): New procedures
+
+	* java.c (PHP_INI_BEGIN): java.log_level changed to PHP_INI_SYSTEM
+
+	* server/php/java/bridge/JavaBridge.java (recycle): New method.
+
+	* server/php/java/bridge/JavaBridgeClassLoader.java (recycle): New method.
+	* server/php/java/bridge/Options.java (recycle): New method.
+
+	* server/php/java/bridge/Request.java (begin, handleRequest):
+	Handle keep-alive.
+	(recycle): New method.
+
+	* server/php/java/bridge/Response.java (recycle): New method.
+
+	* server/php/java/bridge/SessionFactory.java (session): New from
+	getSession.
+	(getSession, getSessionInternal): Keep user sessions and internal
+	sessions for the serialize/desiralize implementation separate.
+
+	* server/php/java/bridge/ThreadPool.java (setIsDaemon,
+	getIsDaemon, terminateDaemon): Daemon's are managed by the pool
+	but are not visible in any way. They are terminated when the
+	associated keep-alive client terminates.
+
+	* server/php/java/servlet/FastCGIServlet.java (override_hosts,
+	init): Use the override_hosts for the FastCGIServlet, too.
+
+	* server/test/HelloWorld.java: Removed ini_set("java.log_level",
+	...), the log_level setting is INI_SYSTEM now. -- None of the
+	examples and none of the documentation mentioned that feature, so
+	we can silently drop it.
+	
 2006-04-23  Jost Boekemeier  <jostb@intern>
 
 	* bind.c (wait_server): Timeout raised to 30 seconds.
Index: INSTALL
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/INSTALL,v
retrieving revision 1.30
diff -u -r1.30 INSTALL
--- INSTALL	12 Apr 2006 17:46:45 -0000	1.30
+++ INSTALL	30 Apr 2006 16:54:56 -0000
@@ -68,7 +68,8 @@
 su - -c "service httpd stop"
 
 # adjust the java version
-JAVA_HOME=/opt/IBMJava2-141
+JAVA_HOME=/opt/jdk1.4.2
+#JRE_HOME=/opt/jre1.6.0 # enable this, if you want to hard-code the JRE path
 
 # The following software components are required during the build
 # process: autoconf 2.57, automake 1.6.3 and libtool 1.4.3. If you
@@ -103,7 +104,7 @@
 #
 bunzip2 < php-x.y.z.tar.bz2 | tar xf -
 cd php-x.y.z
-./configure --prefix=$INST --without-java --with-apxs2=$INST/bin/apxs
+./configure --prefix=$INST --disable-all --with-apxs2=$INST/bin/apxs
 make && su -c "make install"
 # now activate php in the httpd.conf
 su -c "echo 'AddType application/x-httpd-php .php' >>$INST/conf/httpd.conf"
@@ -116,7 +117,7 @@
 bunzip2 < php-java-bridge_p.x.y.tar.bz2 | tar xf -
 cd php-java-bridge-p.x.y
 phpize
-./configure --with-java=$JAVA_HOME
+./configure --with-java=$JAVA_HOME,$JRE_HOME
 make && su -c "make install"
 # now activate the bridge in php.ini
 su -c "touch $INST/lib/php.ini && echo -e 'extension=java.so\n[java]' >>$INST/lib/php.ini"
Index: INSTALL.J2EE
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/INSTALL.J2EE,v
retrieving revision 1.6
diff -u -r1.6 INSTALL.J2EE
--- INSTALL.J2EE	13 Apr 2006 16:09:10 -0000	1.6
+++ INSTALL.J2EE	30 Apr 2006 16:54:56 -0000
@@ -12,9 +12,12 @@
 * Visit http://localhost:<port>/JavaBridge and click on test.php.
   The <port> is 8888 (Oracle), 9080 (WebSphere) or 8080 (Tomcat).
 
+* Please see the README and http://php-java-bridge.sourceforge.net
+  for further information.
+
 
 Installing and testing the front-end on Linux, Unix, Windows
------------------------------------------------------------
+------------------------------------------------------------
 
 NOTE: Linux RPMs contain Security Enhanced Linux contexts. If you want
 to install software on a SEL system (RHEL, Fedora, ...), please use
Index: INSTALL.LINUX
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/INSTALL.LINUX,v
retrieving revision 1.5
diff -u -r1.5 INSTALL.LINUX
--- INSTALL.LINUX	12 Apr 2006 17:46:45 -0000	1.5
+++ INSTALL.LINUX	30 Apr 2006 16:54:56 -0000
@@ -1,7 +1,7 @@
 Installing the PHP/Java Bridge on Linux
 ---------------------------------------
 
-On RedHat Enterprise Linux[1] ("RHEL") or Fedora Linux ("FC")
+On RedHat Enterprise Linux ("RHEL") or Fedora Linux ("FC")
 download and install the java, PHP, httpd and php-java-bridge RPM
 files. On other Linux variants please either create a binary RPM
 distribution from the source RPM (with: rpmbuild --rebuild
@@ -10,19 +10,19 @@
 
 Install the RPM files, for example with:
 
-    rpm -i jdk-1_5_0-linux-i586.rpm
-    rpm -i httpd-2.0.54-10.i386.rpm
-    rpm -i php-5.0.4-10.i386.rpm
-    rpm -i php-java-bridge-x.y.z-1.i386.rpm
+    rpm -i jre-x.y.z-p.i386.rpm
+    rpm -i httpd-2.y.z-p.i386.rpm
+    rpm -i php-x.y.z-p.i386.rpm
+    rpm -i php-java-bridge-x.y.z-p.i386.rpm
 
 Either install the tomcat back-end:
 
-    rpm -i tomcat5-5.0.30-5jpp_6fc.i386.rpm
-    rpm -i php-java-bridge-tomcat-x.y.z-1.i386.rpm
+    rpm -i tomcat5-x.y.z-p.i386.rpm
+    rpm -i php-java-bridge-tomcat-x.y.z-p.i386.rpm
 
 Or install the standalone back-end:
 
-    rpm -i php-java-bridge-standalone-x.y.z-1.i386.rpm
+    rpm -i php-java-bridge-standalone-x.y.z-p.i386.rpm
 
 Or deploy the J2EE back-end:
 
@@ -50,10 +50,10 @@
     http://yourHost/test.php
 
 Then install your java libraries (.jar files) in /usr/share/java or in
-java.libpath/lib (see output of phpinfo) and your PHP and web-pages in
-the web server document root (/var/www/html or
-/usr/share/tomcat5/webapps/JavaBridge) or one of their
-sub-directories.
+java.libpath/lib (see output of phpinfo) or in the J2EE back-end's
+WEB-INF/lib and your PHP and web-pages in the web server document root
+(/var/www/html or /usr/share/tomcat5/webapps/JavaBridge) or one of
+their sub-directories.
 
-[1] On RHEL3 do not use the RPM from CD#9 but download a JRE >= 1.4.2 from
-Sun or IBM instead.
+Please see the README and http://php-java-bridge.sourceforge.net
+for further information.
Index: INSTALL.WINDOWS
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/INSTALL.WINDOWS,v
retrieving revision 1.19
diff -u -r1.19 INSTALL.WINDOWS
--- INSTALL.WINDOWS	13 Apr 2006 16:09:10 -0000	1.19
+++ INSTALL.WINDOWS	30 Apr 2006 16:54:56 -0000
@@ -8,6 +8,12 @@
   http://localhost:<port>/JavaBridge and click on test.php.
   The <port> is 8888 (Oracle), 9080 (WebSphere) or 8080 (Tomcat).
 
+* Please see the README and http://php-java-bridge.sourceforge.net for
+  further information.
+
+
+Installing and testing the front-end on Windows
+-----------------------------------------------
 
 If the above test succeeded (or if you have skipped the test because
 you don't want to use a J2EE server), install a HTTP server, PHP, the
Index: NEWS
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/NEWS,v
retrieving revision 1.14
diff -u -r1.14 NEWS
--- NEWS	12 Apr 2006 17:46:45 -0000	1.14
+++ NEWS	30 Apr 2006 16:54:56 -0000
@@ -3,6 +3,15 @@
 Please send bug reports, questions and suggestions to
 <php-java-bridge-users@lists.sourceforge.net>.
 
+Version 3.1.0:
+
+* Persistent connections: If "java.persistent_connections" is set to
+"On", the Apache/Tomcat combination delivers Java based content faster
+than Tomcat standalone(!) and more than two times faster than
+Apache/Tomcat connected via Tomcat's mod_jk. Tested with Apache
+2.0.49 running PHP 5.1.2 in the slowest configuration (mpm=prefork).
+
+
 Version 3.0.8:
 
 * When the tomcat or J2EE JavaBridge.war "back-end" is used without an
Index: PROTOCOL.TXT
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/PROTOCOL.TXT,v
retrieving revision 1.20
diff -u -r1.20 PROTOCOL.TXT
--- PROTOCOL.TXT	28 Apr 2006 18:15:02 -0000	1.20
+++ PROTOCOL.TXT	30 Apr 2006 16:54:56 -0000
@@ -157,7 +157,7 @@
 v: long
 
 ->
-EOF:
+EndConnection:
 <F p=A|E />
 p: char (Keep [Alive, [E]nd connection)
 
Index: README
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/README,v
retrieving revision 1.87
diff -u -r1.87 README
--- README	12 Apr 2006 17:46:45 -0000	1.87
+++ README	30 Apr 2006 16:54:56 -0000
@@ -20,9 +20,9 @@
           gcc --version        # 3.2.3 or above (4.0.x recommended)
           apachectl -version   # Apache 1.3 or above (2.x recommended)
           php-config --version # PHP 4.3.4 or above (5.x or 6.x recommended)
-          make null --version  # GNU make 3.79 or above
+          make null --version  # GNU make
 
-          phpize && 
+          phpize &&
           ./configure --with-java=/usr/java/default &&
           make &&
           su -c "sh install.sh"
@@ -34,6 +34,8 @@
   Please see the output of ./configure --help=recursive for further
   configure options.
 
+  Please see the INSTALL document for detailed instructions.
+
 ------------------------------------
    Permanently activate the module
    -------------------------------
@@ -131,7 +133,7 @@
   back-end. Example for option:
 
   #1: Not needed, back-end starts automatically
-  #2: /usr/sbin/php-java-bridge (see [note: SERVICE] below)
+  #2: service php-java-bridge restart (see [note: SERVICE] below)
   #3: java -jar JavaBridge.jar INET:9267 3 php-java-bridge.log
   #4: service tomcat5 restart
   #5: service tomcat5 restart
@@ -497,8 +499,12 @@
 
         su -                                      # become super user
         newrole -t initrc_t                       # change domain
-        kill `cat /var/run/php-java-bridge.pid`   # kill old executable
-        /usr/sbin/php-java-bridge                 # start new back-end
+        kill `cat /var/run/php-java-bridge.pid`   # terminate the old process
+        /usr/sbin/php-java-bridge                 # start a new back-end
+
+  or simply use the service script:
+
+        service php-java-bridge restart
 
   Please note that SEL security is orthogonal to the standard Unix 
   security. For example you could also put the java process into 
Index: README.MONO+NET
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/README.MONO+NET,v
retrieving revision 1.6
diff -u -r1.6 README.MONO+NET
--- README.MONO+NET	12 Apr 2006 17:46:46 -0000	1.6
+++ README.MONO+NET	30 Apr 2006 16:54:56 -0000
@@ -1,8 +1,7 @@
 Build and execution instructions:
 ---------------------------------
   NOTE: If you have Security Enhanced Linux, you must update the policy
-  and tag the files with the correct SEL contexts, please see below, or 
-  please install the binary RPM instead.
+  and tag the files with the correct SEL contexts, please see the README.
 
   Install mono 1.1.8 or above. Install the IKVM.GNU.Classpath.dll and
   IKVM.Runtime.dll. Install ikvmc.exe from the IKVM project:
@@ -13,8 +12,8 @@
           mono --version       # 1.0.6 or above.
           gcj --version        # 3.2.3 or above.
           apachectl -version   # Apache 1.3 or above.
-          php-config --version # PHP 4.3.2 or above.
-          make null --version  # GNU make 3.79 or above
+          php-config --version # PHP 4.3.4 or above.
+          make null --version  # GNU make
 
           phpize && 
           ./configure --with-mono=/usr/bin/ikvmc.exe \
@@ -49,16 +48,7 @@
           apachectl restart
 
 
-  OPTION 1: You can use local sockets to connect to a local back-end. 
-  Copy the executable php-mono-bridge to /usr/sbin, make it executable 
-  with the command "chmod +x /usr/sbin/php-mono-bridge" and start it:
-
-          /usr/sbin/php-mono-bridge
-
-  This option can be used if "Security Enhanced Linux" is switched on.
-
-
-  OPTION 2: You can start the bridge as a sub-process of apache. Disable
+  OPTION 1: You can start the bridge as a sub-process of apache. Disable
   mono.socketname, and mono.hosts. For example:
 
           extension = java.so
@@ -72,9 +62,6 @@
           apachectl restart
           pstree | fgrep httpd
 
-  This option cannot be used if "Security Enhanced Linux" is switched
-  on.
-
 
   Check the status:
 
@@ -94,16 +81,9 @@
   ------------------------------------------
 
   When the mono.socketname and mono.hosts options are not set, the web
-  server will start or re-start the bridge automatically as a sub
+  server will start or re-start the mono back-end automatically as a sub
   component when the HTTP service is started or re-started.
 
-  However, when running the bridge in a production environment, it is
-  recommended to start the PHP/Mono Bridge as a system service,
-  independent of the web server. The script "php-mono-bridge.service"
-  can be used on SysV based init systems to automatically start and stop
-  the bridge as a system service.  Please see the RedHat RPM download
-  for an example.
-
 ------------------------------------
   Mailing List
   ------------
Index: VERSION
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/VERSION,v
retrieving revision 1.47
diff -u -r1.47 VERSION
--- VERSION	20 Apr 2006 17:16:08 -0000	1.47
+++ VERSION	30 Apr 2006 16:54:56 -0000
@@ -1 +1 @@
-3.1.0
+3.1.0devel
Index: client.c
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/client.c,v
retrieving revision 1.92
diff -u -r1.92 client.c
--- client.c	26 Apr 2006 19:09:31 -0000	1.92
+++ client.c	30 Apr 2006 16:54:56 -0000
@@ -511,10 +511,12 @@
 	  (*env)->peer_redirected = 1;
 	  JG(ini_user)&=~(U_SERVLET|U_SOCKNAME);
 
-	  assert((*env)->peer!=-1); if((*env)->peer!=-1) close((*env)->peer);
+	  assert((*env)->peer!=-1); 
+	  if((*env)->peer!=-1) { close((*env)->peer); (*env)->peer=-1; }
 	  EXT_GLOBAL(redirect)(env, JG(redirect_port), JG(channel_in), JG(channel_out) TSRMLS_CC);
 	} else {
-	  assert((*env)->peer!=-1); if((*env)->peer!=-1) close((*env)->peer);
+	  assert((*env)->peer!=-1); 
+	  if((*env)->peer!=-1) close((*env)->peer);
 	  server = EXT_GLOBAL(test_server)(&(*env)->peer, 0, 0 TSRMLS_CC);
 	  assert(server); if(!server) exit(9);
 	  free(server);
@@ -526,6 +528,8 @@
   }
 }
 
+
+
 unsigned char EXT_GLOBAL (get_mode) () {
 #ifndef ZEND_ENGINE_2
   // we want arrays as values
@@ -638,13 +642,15 @@
 	(*env)->servlet_context_string = strdup(servlet_context_string);
   if((SUCCESS==zend_eval_string((char*)context, &val, (char*)name TSRMLS_CC)) && (Z_TYPE(val)==IS_STRING)) {
 	(*env)->servlet_ctx = strdup(Z_STRVAL(val));
-								/* backend must have created a session
+								/* back-end must have created a session
 								   proxy, otherwise we wouldn't see a
 								   context. */
 	(*env)->backend_has_session_proxy = 1;	
   }
   return env;
 }
+
+static void init_channel(TSRMLS_D);
 static proxyenv *try_connect_to_server(short bail TSRMLS_DC) {
   char *server;
   int sock;
@@ -653,19 +659,25 @@
   proxyenv *jenv =JG(jenv);
   if(jenv) return jenv;
 
+  EXT_GLOBAL(clone_cfg)(TSRMLS_C);
+
   if(!EXT_GLOBAL(cfg)->is_cgi_servlet || EXT_GLOBAL(cfg)->is_fcgi_servlet) 
 	override_ini_for_redirect(TSRMLS_C);
 
   if(JG(is_closed)) {
 	php_error(E_ERROR, "php_mod_"/**/EXT_NAME()/**/"(%d): Could not connect to server: Session is closed. -- This usually means that you have tried to access the server in your class' __destruct() method.",51);
+	EXT_GLOBAL(destroy_cloned_cfg)(TSRMLS_C);
 	return 0;
   }
   if(!(server=EXT_GLOBAL(test_server)(&sock, &is_local, &saddr TSRMLS_CC))) {
 	if (bail) 
 	  EXT_GLOBAL(sys_error)("Could not connect to server. Have you started the "/**/EXT_NAME()/**/" backend (either a servlet engine, an application server, JavaBridge.jar or MonoBridge.exe) and set the "/**/EXT_NAME()/**/".socketname or "/**/EXT_NAME()/**/".hosts option?",52);
+	EXT_GLOBAL(destroy_cloned_cfg)(TSRMLS_C);
 	return 0;
   }
 
+  init_channel(TSRMLS_C);
+
   jenv = EXT_GLOBAL(createSecureEnvironment)
 	(sock, handle_request, handle_cached, server, is_local, &saddr);
   
@@ -690,7 +702,7 @@
 
 #ifdef __MINGW32__
 /* named pipes are not available on windows */
-void EXT_GLOBAL(init_channel)(TSRMLS_D) {
+static void init_channel(TSRMLS_D) {
   JG(channel_in) = JG(channel_out) = JG(channel) = 0;
 }
 void EXT_GLOBAL(destroy_channel)(TSRMLS_D) {
@@ -722,7 +734,7 @@
   *e=0;
   JG(channel) = basename;
 }
-void EXT_GLOBAL(init_channel)(TSRMLS_D) {
+static void init_channel(TSRMLS_D) {
   static const char sockname[] = SOCKNAME;
   static const char sockname_shm[] = SOCKNAME_SHM;
   static const char length = sizeof(sockname)>sizeof(sockname_shm)?sizeof(sockname):sizeof(sockname_shm);
@@ -762,6 +774,18 @@
   if(channel) return channel;
   return empty;
 }
+void EXT_GLOBAL(clone_cfg)(TSRMLS_D) {
+  JG(ini_user)=EXT_GLOBAL(ini_user);
+  JG(hosts)=strdup(EXT_GLOBAL(cfg)->hosts);
+  JG(servlet)=strdup(EXT_GLOBAL(cfg)->servlet);
+}
+void EXT_GLOBAL(destroy_cloned_cfg)(TSRMLS_D) {
+  if(JG(hosts)) free(JG(hosts));
+  if(JG(servlet)) free(JG(servlet));
+  JG(ini_user)=0;
+  JG(hosts)=0;
+  JG(servlet)=0;
+}
 
 #ifndef PHP_WRAPPER_H
 #error must include php_wrapper.h
Index: init_cfg.c.in
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/init_cfg.c.in,v
retrieving revision 1.29
diff -u -r1.29 init_cfg.c.in
--- init_cfg.c.in	28 Apr 2006 18:15:02 -0000	1.29
+++ init_cfg.c.in	30 Apr 2006 16:54:56 -0000
@@ -151,6 +151,7 @@
   if(!(EXT_GLOBAL (ini_updated) &U_JAVA)) EXT_GLOBAL(cfg)->vm=strdup(CFG_JAVA);
   if(!(EXT_GLOBAL (ini_updated) &U_JAVA_HOME)) EXT_GLOBAL(cfg)->vm_home=strdup(CFG_JAVA_HOME);
   if(!(EXT_GLOBAL (ini_updated) &U_EXT_JAVA_COMPATIBILITY)) EXT_GLOBAL(cfg)->extJavaCompatibility=0;
+  if(!(EXT_GLOBAL (ini_updated) &U_PERSISTENT_CONNECTIONS)) EXT_GLOBAL(cfg)->persistent_connections=0;
   if(!(EXT_GLOBAL (ini_updated) &U_LOGLEVEL)) {
 	EXT_GLOBAL(cfg)->logLevel=strdup(DEFAULT_LEVEL);
 	EXT_GLOBAL(cfg)->logLevel_val=atoi(DEFAULT_LEVEL);
@@ -206,6 +207,7 @@
   case U_SERVLET: entry = EXT_GLOBAL(cfg)->servlet; break;
   case U_WRAPPER: entry = EXT_GLOBAL(cfg)->wrapper; break;
   case U_EXT_JAVA_COMPATIBILITY: return EXT_GLOBAL(cfg)->extJavaCompatibility;
+  case U_PERSISTENT_CONNECTIONS: return EXT_GLOBAL(cfg)->persistent_connections;
   default: assert(0);
   }  
 
Index: java.c
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/java.c,v
retrieving revision 1.119
diff -u -r1.119 java.c
--- java.c	28 Apr 2006 18:21:25 -0000	1.119
+++ java.c	30 Apr 2006 16:54:57 -0000
@@ -43,33 +43,14 @@
   php_info_print_table_row_ex(a, "v", b, c)
 #endif
 
-static void clone_cfg(TSRMLS_D) {
-  JG(ini_user)=EXT_GLOBAL(ini_user);
-  JG(hosts)=strdup(EXT_GLOBAL(cfg)->hosts);
-  JG(servlet)=strdup(EXT_GLOBAL(cfg)->servlet);
-}
-static void destroy_cloned_cfg(TSRMLS_D) {
-  if(JG(hosts)) free(JG(hosts));
-  if(JG(servlet)) free(JG(servlet));
-  JG(ini_user)=0;
-  JG(hosts)=0;
-  JG(servlet)=0;
-}
-
 /**
  * Called when a new request starts.  Opens a connection to the
- * backend, creates an instance of the proxyenv structure and clones
+ * back-end, creates an instance of the proxyenv structure and clones
  * the servlet, hosts and ini_user flags.
  */
 PHP_RINIT_FUNCTION(EXT) 
 {
-  if(EXT_GLOBAL(cfg)) {
-	clone_cfg(TSRMLS_C);
-  }
-
-  EXT_GLOBAL(init_channel)(TSRMLS_C);
-
-  if(JG(jenv)) {
+  if(!EXT_GLOBAL(cfg)->persistent_connections && JG(jenv)) {
 	php_error(E_ERROR, "php_mod_"/**/EXT_NAME()/**/"(%d): Synchronization problem, rinit with active connection called. Cannot continue, aborting now. Please report this to: php-java-bridge-users@lists.sourceforge.net",59);
   }
   JG(is_closed)=0;
@@ -78,34 +59,11 @@
 
 /**
  * Called when the request terminates. Closes the connection to the
- * backend, destroys the proxyenv instance.
+ * back-end, destroys the proxyenv instance.
  */
 PHP_RSHUTDOWN_FUNCTION(EXT)
 {
-  destroy_cloned_cfg(TSRMLS_C);
-
-  if(JG(jenv)) {
-	if(*JG(jenv)) {
-	  if((*JG(jenv))->peer!=-1) {
-		/* end servlet session */
-		EXT_GLOBAL(protocol_end)(JG(jenv));
-		close((*JG(jenv))->peer);
-		if((*JG(jenv))->peerr!=-1) close((*JG(jenv))->peerr);
-		if((*JG(jenv))->peer0!=-1) close((*JG(jenv))->peer0);
-	  }
-	  if((*JG(jenv))->s) free((*JG(jenv))->s);
-	  if((*JG(jenv))->send) free((*JG(jenv))->send);
-	  if((*JG(jenv))->server_name) free((*JG(jenv))->server_name);
-	  if((*JG(jenv))->servlet_ctx) free((*JG(jenv))->servlet_ctx);
-	  if((*JG(jenv))->servlet_context_string) free((*JG(jenv))->servlet_context_string);
-	  free(*JG(jenv));
-	}
-	free(JG(jenv));
-  }
-
-  JG(jenv) = NULL;
-  EXT_GLOBAL(destroy_channel)(TSRMLS_C);
-
+  EXT_GLOBAL(close_connection) (&JG(jenv), EXT_GLOBAL(cfg)->persistent_connections TSRMLS_CC);
   JG(is_closed)=1;
   return SUCCESS;
 }
@@ -226,7 +184,7 @@
  * call java_require("foo.jar"); java_require("bar.jar"), the classes
  * from foo cannot see the classes loaded from bar. If you get a
  * NoClassDefFound error saying that one of your classes cannot
- * access the library you have loaded, you must reset the backend to
+ * access the library you have loaded, you must reset the back-end to
  * clear the loader cache and load your classes and the library in one
  * java_require() call.
  */
@@ -300,7 +258,7 @@
 
   assert(EXT_GLOBAL(cfg)->is_cgi_servlet && (*jenv)->servlet_ctx ||!EXT_GLOBAL(cfg)->is_cgi_servlet);
 								/* create a new connection to the
-								   backend if java_session() is not
+								   back-end if java_session() is not
 								   the first statement in a script */
   EXT_GLOBAL(check_session) (jenv TSRMLS_CC);
 
@@ -394,11 +352,11 @@
 /**
  * Proto: string java_server_name(void) or string java_get_server_name(void)
  *
- * Returns the name of the backend or null, if the backend is not running. Example:
+ * Returns the name of the back-end or null, if the back-end is not running. Example:
  * \code
  * $backend = java_get_server_name();
- * if(!$backend) wakeup_administrator("backend not running");
- * echo "Connected to the backend: $backend\n";
+ * if(!$backend) wakeup_administrator("back-end not running");
+ * echo "Connected to the back-end: $backend\n";
  * \endcode
  */
 EXT_FUNCTION(EXT_GLOBAL(get_server_name))
@@ -421,11 +379,11 @@
  * caches are gone. 
  *
  * Example:
- * \code echo "Resetting backend to initial state\n";
+ * \code echo "Resetting back-end to initial state\n";
  * java_reset();
  * \endcode
  *
- * This procedure does nothing when the backend runs
+ * This procedure does nothing when the back-end runs
  * in a servlet environment or an application server. 
  */
 EXT_FUNCTION(EXT_GLOBAL(reset))
@@ -438,14 +396,14 @@
 
   (*jenv)->writeInvokeBegin(jenv, 0, "reset", 0, 'I', return_value);
   (*jenv)->writeInvokeEnd(jenv);
-  php_error(E_WARNING, "php_mod_"/**/EXT_NAME()/**/"(%d): Your script has called the privileged procedure \""/**/EXT_NAME()/**/"_reset()\" which resets the "/**/EXT_NAME()/**/" backend to its initial state. Therefore all "/**/EXT_NAME()/**/" caches are gone.", 18);
+  php_error(E_WARNING, "php_mod_"/**/EXT_NAME()/**/"(%d): Your script has called the privileged procedure \""/**/EXT_NAME()/**/"_reset()\" which resets the "/**/EXT_NAME()/**/" back-end to its initial state. Therefore all "/**/EXT_NAME()/**/" caches are gone.", 18);
 }
 
 /**
  * Proto: void java_begin_document(void)
  *
  * Enters stream mode (asynchronuous protocol). The statements are
- * sent to the backend in one XML stream.
+ * sent to the back-end in one XML stream.
 */
 EXT_FUNCTION(EXT_GLOBAL(begin_document))
 {
@@ -1040,6 +998,17 @@
 	}
 	return SUCCESS;
 }
+static PHP_INI_MH(OnIniPersistentConnections)
+{
+	if (new_value) {
+	  if(!strncasecmp(on, new_value, 2) || !strncasecmp(on2, new_value, 1))
+		EXT_GLOBAL(cfg)->persistent_connections=1;
+	  else
+		EXT_GLOBAL(cfg)->persistent_connections=0;
+	  EXT_GLOBAL(ini_updated)|=U_PERSISTENT_CONNECTIONS;
+	}
+	return SUCCESS;
+}
 static PHP_INI_MH(OnIniServlet)
 {
   if (new_value) {
@@ -1139,9 +1108,10 @@
   PHP_INI_ENTRY(EXT_NAME()/**/"."/**/EXT_NAME()/**/"",   NULL, PHP_INI_SYSTEM, OnIniJava)
   PHP_INI_ENTRY(EXT_NAME()/**/"."/**/EXT_NAME()/**/"_home",   NULL, PHP_INI_SYSTEM, OnIniJavaHome)
 
-  PHP_INI_ENTRY(EXT_NAME()/**/".log_level",   NULL, PHP_INI_ALL, OnIniLogLevel)
+  PHP_INI_ENTRY(EXT_NAME()/**/".log_level",   NULL, PHP_INI_SYSTEM, OnIniLogLevel)
   PHP_INI_ENTRY(EXT_NAME()/**/".log_file",   NULL, PHP_INI_SYSTEM, OnIniLogFile)
   PHP_INI_ENTRY(EXT_NAME()/**/".ext_java_compatibility",   NULL, PHP_INI_SYSTEM, OnIniExtJavaCompatibility)
+  PHP_INI_ENTRY(EXT_NAME()/**/".persistent_connections",   NULL, PHP_INI_SYSTEM, OnIniPersistentConnections)
   PHP_INI_END()
 
 /* vm_alloc_globals_ctor(zend_vm_globals *vm_globals) */
@@ -2029,9 +1999,9 @@
 
 /**
  * Called when the module is initialized. Creates the Java and
- * JavaClass structures and tries to start the backend if
+ * JavaClass structures and tries to start the back-end if
  * java.socketname, java.servlet or java.hosts are not set.  The
- * backend is not started if the environment variable
+ * back-end is not started if the environment variable
  * X_JAVABRIDGE_OVERRIDE_HOSTS exists and contains either "/" or
  * "host:port//context/servlet".  When running as a Apache/IIS module
  * or Fast CGI, this procedure is called only once. When running as a
@@ -2146,9 +2116,9 @@
 	EXT_GLOBAL(init_cfg) (TSRMLS_C);
 
 	make_local_socket_info(TSRMLS_C);
-	clone_cfg(TSRMLS_C);
+	EXT_GLOBAL(clone_cfg)(TSRMLS_C);
 	EXT_GLOBAL(start_server) (TSRMLS_C);
-	destroy_cloned_cfg(TSRMLS_C);
+	EXT_GLOBAL(destroy_cloned_cfg)(TSRMLS_C);
   } 
   return SUCCESS;
 }
@@ -2188,7 +2158,7 @@
 	else
 	  php_info_print_table_row(2, EXT_NAME()/**/".log_file", EXT_GLOBAL(cfg)->logFile);
   }
-  php_info_print_table_row(2, EXT_NAME()/**/".log_level", is_level ? EXT_GLOBAL(cfg)->logLevel : "no value (use backend's default level)");
+  php_info_print_table_row(2, EXT_NAME()/**/".log_level", is_level ? EXT_GLOBAL(cfg)->logLevel : "no value (use back-end's default level)");
   if(EXT_GLOBAL(option_set_by_user) (U_HOSTS, EXT_GLOBAL(ini_user)))  
 	php_info_print_table_row(2, EXT_NAME()/**/".hosts", JG(hosts));
 #if EXTENSION == JAVA
@@ -2200,6 +2170,7 @@
 #else
   php_info_print_table_row(2, EXT_NAME()/**/".ext_java_compatibility", EXT_GLOBAL(cfg)->extJavaCompatibility?on:off);
 #endif
+  php_info_print_table_row(2, EXT_NAME()/**/".persistent_connections", EXT_GLOBAL(cfg)->persistent_connections?on:off);
   php_info_print_table_row(2, EXT_NAME()/**/" command", s);
   php_info_print_table_row(2, EXT_NAME()/**/" status", server?"running":"not running");
   php_info_print_table_row(2, EXT_NAME()/**/" server", server?server:"localhost");
@@ -2210,13 +2181,14 @@
 }
 
 /**
- * Called when the module terminates. Stops the backend, if it is running.
+ * Called when the module terminates. Stops the back-end, if it is running.
  * When running in Apache/IIS or as a FastCGI binary, this procedure is 
  * called only once. When running as a CGI binary this is called whenever
  * the CGI binary terminates.
  */
 PHP_MSHUTDOWN_FUNCTION(EXT) 
 {
+  EXT_GLOBAL(close_connection) (&JG(jenv), 0 TSRMLS_CC);
   EXT_GLOBAL(destroy_cfg) (EXT_GLOBAL(ini_set));
   EXT_GLOBAL(ini_user) = EXT_GLOBAL(ini_set) = 0;
 
Index: java_bridge.h
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/java_bridge.h,v
retrieving revision 1.27
diff -u -r1.27 java_bridge.h
--- java_bridge.h	12 Mar 2006 16:44:39 -0000	1.27
+++ java_bridge.h	30 Apr 2006 16:54:57 -0000
@@ -39,13 +39,11 @@
 extern proxyenv *EXT_GLOBAL(createSecureEnvironment) (int peer, void (*handle_request)(proxyenv *env), void (*handle_cached)(proxyenv *env), char*server, short is_local, struct sockaddr*saddr);
 extern void EXT_GLOBAL(redirect)(proxyenv*env, char*redirect_port, char*channel_in, char*channel_out TSRMLS_DC);
 
-extern void EXT_GLOBAL(init_channel)(TSRMLS_D);
 extern void EXT_GLOBAL(destroy_channel)(TSRMLS_D);
 extern const char*EXT_GLOBAL(get_channel)(TSRMLS_D);
 
 extern void EXT_GLOBAL (begin_async) (proxyenv*env);
 extern void EXT_GLOBAL (end_async) (proxyenv*env);
-extern void EXT_GLOBAL (protocol_end) (proxyenv *env);
 extern void EXT_GLOBAL (check_session) (proxyenv *env TSRMLS_DC);
 extern void EXT_GLOBAL (setResultWith_context) (char*key, char*val, char*path);
 extern short EXT_GLOBAL (option_set_by_user) (short option, int where);
Index: php-java-bridge.spec
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/php-java-bridge.spec,v
retrieving revision 1.59
diff -u -r1.59 php-java-bridge.spec
--- php-java-bridge.spec	20 Apr 2006 17:16:08 -0000	1.59
+++ php-java-bridge.spec	30 Apr 2006 16:54:57 -0000
@@ -1,5 +1,5 @@
 #-*- mode: rpm-spec; tab-width:4 -*-
-%define version 3.1.0
+%define version 3.1.0devel
 %define release 1
 %define PHP_MAJOR_VERSION %(((LANG=C rpm -q --queryformat "%{VERSION}" php) || echo "4.0.0") | tail -1 | sed 's/\\\..*$//')
 %define PHP_MINOR_VERSION %(((LANG=C rpm -q --queryformat "%{VERSION}" php) || echo "4.0.0") | tail -1 | LANG=C cut -d. -f2)
Index: php_java.h
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/php_java.h,v
retrieving revision 1.55
diff -u -r1.55 php_java.h
--- php_java.h	28 Apr 2006 18:15:02 -0000	1.55
+++ php_java.h	30 Apr 2006 16:54:57 -0000
@@ -92,6 +92,7 @@
 #define U_SERVLET (1<<9)
 #define U_WRAPPER (1<<10)
 #define U_EXT_JAVA_COMPATIBILITY  (1<<11)
+#define U_PERSISTENT_CONNECTIONS  (1<<12)
 
 #if EXTENSION == JAVA
 #define phpext_java_ptr &EXT_GLOBAL(module_entry)
@@ -157,6 +158,7 @@
   short socketname_set;
   /** 0: Compatibility with ext/java is off (default), 1: on  */
   short extJavaCompatibility;
+  short persistent_connections;
 };
 extern struct cfg *EXT_GLOBAL(cfg);
 
@@ -195,10 +197,12 @@
 #endif
 
 extern char* EXT_GLOBAL(get_server_string)(TSRMLS_D);
-
 extern proxyenv *EXT_GLOBAL(try_connect_to_server)(TSRMLS_D);
 extern proxyenv *EXT_GLOBAL(connect_to_server)(TSRMLS_D);
+extern void EXT_GLOBAL(close_connection)(proxyenv**env, short persistent_connection TSRMLS_DC);
 extern void EXT_GLOBAL(start_server)(TSRMLS_D);
+extern void EXT_GLOBAL(clone_cfg)(TSRMLS_D);
+extern void EXT_GLOBAL(destroy_cloned_cfg)(TSRMLS_D);
 
 extern char* EXT_GLOBAL(test_server)(int *socket, short *is_local, struct sockaddr*saddr TSRMLS_DC);
 
Index: protocol.c
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/protocol.c,v
retrieving revision 1.43
diff -u -r1.43 protocol.c
--- protocol.c	28 Apr 2006 18:15:02 -0000	1.43
+++ protocol.c	30 Apr 2006 16:54:57 -0000
@@ -88,7 +88,7 @@
 	int header_length;
 	unsigned char mode = EXT_GLOBAL (get_mode) ();
 
-	assert(!(*env)->peer_redirected || ((*env)->peer_redirected && ((*env)->peer0)!=-1));
+	assert(!(*env)->peer_redirected || ((*env)->peer_redirected && ((*env)->peer0)==-1));
 	header_length=EXT_GLOBAL(snprintf) (header, sizeof(header), "PUT %s HTTP/1.1\r\nHost: localhost\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\nContent-Length: %lu\r\nX_JAVABRIDGE_CHANNEL: %s\r\nX_JAVABRIDGE_CONTEXT: %s\r\n\r\n%c", servlet_context, (unsigned long)(size+1), EXT_GLOBAL(get_channel)(TSRMLS_C), getSessionFactory(env), mode);
 
 	add_header(env, &size, header, header_length);
@@ -142,7 +142,6 @@
 
   (*env)->finish=end;
   
-  assert(!(*env)->peer_redirected || ((*env)->peer_redirected && ((*env)->peer0)!=-1));
   header_length=EXT_GLOBAL(snprintf) (header, sizeof(header), "PUT %s HTTP/1.1\r\nHost: localhost\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\nContent-Length: %lu\r\nX_JAVABRIDGE_REDIRECT: %d\r\n%sX_JAVABRIDGE_CHANNEL: %s\r\nX_JAVABRIDGE_CONTEXT: %s\r\n\r\n%c", (*env)->servlet_context_string, (unsigned long)(size+1), override_redirect, get_cookies(&val, env), EXT_GLOBAL(get_channel)(TSRMLS_C), getSessionFactory(env), mode);
 
   add_header(env, &size, header, header_length);
@@ -156,7 +155,7 @@
   (*env)->handle(env);
 }
 
-void EXT_GLOBAL (protocol_end) (proxyenv *env) {
+void protocol_end (proxyenv *env) {
   char *servlet_context;
   short context_length = 0;
   char *context;
@@ -184,6 +183,7 @@
 	add_header(env, &size, context, context_length);
 	send_data(env, (char*)(*env)->send, size);
   }
+  (*env)->send_len=0;
 }
 static ssize_t send_async(proxyenv*env, const void*buf, size_t length) {
   return (ssize_t)fwrite(buf, 1ul, length, (*env)->async_ctx.peer);
@@ -396,6 +396,14 @@
    end(env);
  }
 
+ static void EndConnection(proxyenv *env, char property) {
+   size_t flen;
+   assert(property=='A' || property=='E');
+   GROW(FLEN);
+   (*env)->send_len+=EXT_GLOBAL(snprintf)((char*)((*env)->send+(*env)->send_len), flen, "<F p=\"%c\"/>", property);
+   assert((*env)->send_len<=(*env)->send_size);
+ }
+
  static void String(proxyenv *env, char*name, size_t _len) {
    size_t flen;
    static const char Sb[]="<S v=\"";
@@ -505,7 +513,55 @@
 
  
 
- proxyenv *EXT_GLOBAL(createSecureEnvironment) (int peer, void (*handle_request)(proxyenv *env), void (*handle_cached)(proxyenv *env), char *server_name, short is_local, struct sockaddr *saddr) {
+static void close_connection(proxyenv**penv TSRMLS_DC) {
+  if(*penv) {
+	proxyenv *env = *penv;
+	if(*env) {
+	  if((*env)->peer!=-1) {
+		/* end servlet session */
+		(*env)->writeEndConnection(env, 'E');
+		protocol_end(env);
+		close((*env)->peer);
+		if((*env)->peerr!=-1) close((*env)->peerr);
+		if((*env)->peer0!=-1) close((*env)->peer0);
+	  }
+	  if((*env)->s) free((*env)->s);
+	  if((*env)->send) free((*env)->send);
+	  if((*env)->server_name) free((*env)->server_name);
+	  if((*env)->servlet_ctx) free((*env)->servlet_ctx);
+	  if((*env)->servlet_context_string) free((*env)->servlet_context_string);
+	  free(*env);
+	}
+	free(env);
+  }
+
+  *penv = 0;
+  EXT_GLOBAL(destroy_channel)(TSRMLS_C);
+  EXT_GLOBAL(destroy_cloned_cfg)(TSRMLS_C);
+}
+static void recycle_connection(proxyenv *env TSRMLS_DC) {
+  if(env && *env) {
+	if((*env)->peer!=-1) {
+	  /* end servlet session */
+	  (*env)->writeEndConnection(env, 'A');
+	  protocol_end(env);
+
+	  if((*env)->servlet_ctx) {
+		free((*env)->servlet_ctx);
+		(*env)->servlet_ctx = 0;
+	  }
+	  
+	  (*env)->backend_has_session_proxy = 0;
+	}
+  }
+}
+void EXT_GLOBAL(close_connection)(proxyenv**penv, short persistent_connection TSRMLS_DC) {
+  if(persistent_connection) 
+	recycle_connection(*penv TSRMLS_CC);
+  else
+	close_connection(penv TSRMLS_CC);
+}
+proxyenv *EXT_GLOBAL(createSecureEnvironment) (int peer, void (*handle_request)(proxyenv *env), void (*handle_cached)(proxyenv *env), char *server_name, short is_local, struct sockaddr *saddr) {
    proxyenv *env;  
    env=(proxyenv*)malloc(sizeof *env);     
    if(!env) return 0;
@@ -565,6 +621,7 @@
    (*env)->writePairBegin_n=PairBegin_n;
    (*env)->writePairEnd=PairEnd;
    (*env)->writeUnref=Unref;
+   (*env)->writeEndConnection=EndConnection;
    (*env)->finish=end;
 
    return env;
Index: protocol.h
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/protocol.h,v
retrieving revision 1.36
diff -u -r1.36 protocol.h
--- protocol.h	12 Mar 2006 16:44:39 -0000	1.36
+++ protocol.h	30 Apr 2006 16:54:57 -0000
@@ -132,6 +132,7 @@
   void (*writePairBegin)(proxyenv *env);
   void (*writePairEnd)(proxyenv *env);
   void (*writeUnref)(proxyenv *env, long object);
+  void (*writeEndConnection)(proxyenv *env, char property);
   void (*finish)(proxyenv *env);
 
   ssize_t (*f_recv)(proxyenv*env, void *buf, size_t len);
Index: examples/J2EE/SOAP/addNumbers.php
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/examples/J2EE/SOAP/addNumbers.php,v
retrieving revision 1.2
diff -u -r1.2 addNumbers.php
--- examples/J2EE/SOAP/addNumbers.php	26 Apr 2006 19:13:40 -0000	1.2
+++ examples/J2EE/SOAP/addNumbers.php	30 Apr 2006 16:54:57 -0000
@@ -5,7 +5,6 @@
   * This example uses the PHP/Java Bridge to connect to a SOAP service.
   */
 
-ini_set("java.log_level", "1"); // do not print java exceptions for this test
 include("wsimport.php");
 
 try {
Index: server/php/java/bridge/JavaBridge.java
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/server/php/java/bridge/JavaBridge.java,v
retrieving revision 1.93
diff -u -r1.93 JavaBridge.java
--- server/php/java/bridge/JavaBridge.java	12 Apr 2006 17:46:49 -0000	1.93
+++ server/php/java/bridge/JavaBridge.java	30 Apr 2006 16:54:57 -0000
@@ -212,7 +212,7 @@
 	    }
 
 	    globalRef=null;
-	    getClassLoader().clear();
+	    cl.clear();
 	    Session.expire(this);
 	    Util.logDebug("END: JavaBridge.run()");
 
@@ -1529,7 +1529,9 @@
         this.sessionFactory = sessionFactory;
     }
 
-    static final String PHPSESSION = "PHPSESSION";
+    protected static final String PHPSESSION = "PHPSESSION";
+    protected static final String INTERNAL_PHPSESSION = "INTERNAL_PHPSESSION";
+
     /**
      * Load the object from the session store.
      * The C code requires that this method is called "deserialize" even though it doesn't deserialize anything.
@@ -1716,5 +1718,14 @@
 	int i = ((Number)pos).intValue();
 	Array.set(value, i, null);
     }
-
+    /** re-initialize for keep-alive */
+    protected void recycle() {
+	Session.expire(this);
+	sessionCache = null;
+        globalRef = new GlobalRef(this);
+        lastException = lastAsyncException = null;
+	cl.recycle();
+        options.recycle();
+        request.recycle();
+    }
 }
Index: server/php/java/bridge/JavaBridgeClassLoader.java
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/server/php/java/bridge/JavaBridgeClassLoader.java,v
retrieving revision 1.30
diff -u -r1.30 JavaBridgeClassLoader.java
--- server/php/java/bridge/JavaBridgeClassLoader.java	26 Apr 2006 19:09:32 -0000	1.30
+++ server/php/java/bridge/JavaBridgeClassLoader.java	30 Apr 2006 16:54:57 -0000
@@ -103,4 +103,11 @@
     public void clear() {
 	if(!checkCl()) cl.clear();
     }
+    
+    /** re-initialize for keep alive */
+    protected void recycle() {
+      	clear();
+      	cachedPath = null;
+	cachedExtensionDir = null;
+    }
 }
Index: server/php/java/bridge/Options.java
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/server/php/java/bridge/Options.java,v
retrieving revision 1.4
diff -u -r1.4 Options.java
--- server/php/java/bridge/Options.java	28 Dec 2005 22:44:33 -0000	1.4
+++ server/php/java/bridge/Options.java	30 Apr 2006 16:54:57 -0000
@@ -84,4 +84,9 @@
         else
             return (new Long(st.getLongValue()));
     }
+    
+    /** re-initialize for keep alive */
+    protected void recycle() {
+        encoding = Util.UTF8;
+    }
 }
Index: server/php/java/bridge/Request.java
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/server/php/java/bridge/Request.java,v
retrieving revision 1.32
diff -u -r1.32 Request.java
--- server/php/java/bridge/Request.java	19 Mar 2006 14:42:46 -0000	1.32
+++ server/php/java/bridge/Request.java	30 Apr 2006 16:54:57 -0000
@@ -362,6 +362,11 @@
 	    arg.id=st[2].getLongValue();
 	    break;
 	}
+	case 'F': {
+	    arg.type=ch;
+	    arg.predicate = st[0].string[st[0].off]=='A';
+	    break;
+	}
 	case 'R': {
 	    arg.type=ch;
 	    arg.id=st[0].getLongValue();
@@ -474,6 +479,19 @@
 		    bridge.CreateObject((String)arg.callObject, true, arg.getArgs(), response);
 		response.flush();
 		break;
+	   case 'F': 
+	         if(arg.predicate) { // keep alive
+	           bridge.recycle();
+	           try {
+	     	       ((ThreadPool.Delegate)Thread.currentThread()).setIsDaemon(true);
+	           } catch (ClassCastException ex) {/*no thread pool*/}
+	         } else { // terminate or terminate keep alive
+	           try {
+	               ThreadPool.Delegate delegate = ((ThreadPool.Delegate)Thread.currentThread()); 
+	               if(delegate.isDaemon()) delegate.terminateDaemon(); // remove keep alive daemon from pool
+	           } catch (ClassCastException ex) {/*no thread pool*/}
+	         }
+	         break;
 	   case 'R':
 	       setIllegalStateException(SUB_FAILED);
 	       response.flush();
@@ -545,4 +563,11 @@
     public void reset() {
 	parser.reset();
     }
+    
+    /** re-initialize for new requests */
+    public void recycle() {
+        reset();
+        arg.reset();
+        response.recycle();
+    }
 }
Index: server/php/java/bridge/Response.java
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/server/php/java/bridge/Response.java,v
retrieving revision 1.37
diff -u -r1.37 Response.java
--- server/php/java/bridge/Response.java	12 Apr 2006 17:46:49 -0000	1.37
+++ server/php/java/bridge/Response.java	30 Apr 2006 16:54:57 -0000
@@ -666,6 +666,10 @@
     protected void reset() {
 	writer.reset();
     }
+    /** re-initialize for keep alive */
+    protected void recycle() {
+        reset();
+    }
     public String toString() {
     	return bridge.options.newString(buf.getFirstBytes());
     }
Index: server/php/java/bridge/SessionFactory.java
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/server/php/java/bridge/SessionFactory.java,v
retrieving revision 1.3
diff -u -r1.3 SessionFactory.java
--- server/php/java/bridge/SessionFactory.java	23 Nov 2005 19:11:16 -0000	1.3
+++ server/php/java/bridge/SessionFactory.java	30 Apr 2006 16:54:57 -0000
@@ -14,34 +14,48 @@
  *
  */
 public class SessionFactory {
-    	
-    /**
-     * @param name The session name. If name is null, the session is an internal session
-     * @param clientIsNew true if the client wants a new session
-     * @param timeout timeout in seconds. If 0 the session does not expire.
-     */
-    public ISession getSession(String name, boolean clientIsNew, int timeout) {
-	if(name==null) name=JavaBridge.PHPSESSION; else name="@"+name;
+  
+  private ISession session(String name, boolean clientIsNew, int timeout) {
 	synchronized(JavaBridge.sessionHash) {
 	    Session ref = null;
 	    if(!JavaBridge.sessionHash.containsKey(name)) {
 		ref = new Session(name);
+		JavaBridge.sessionHash.put(name, ref);
 	    } else {
 		ref = (Session) JavaBridge.sessionHash.get(name);
 		if(clientIsNew) { // client side gc'ed, destroy server ref now!
 		    ref.destroy();
 		    ref = new Session(name);
+		    JavaBridge.sessionHash.put(name, ref);
 		} else {
 		    ref.isNew=false;
 		}
 	    }
 		    	    
 	    ref.setTimeout(timeout);
-	    JavaBridge.sessionHash.put(name, ref);
 	    return ref;
 	}
-			
-    }
+  }
+  /**
+   * @param name The session name. If name is null, the session is an internal session
+   * @param clientIsNew true if the client wants a new session
+   * @param timeout timeout in seconds. If 0 the session does not expire.
+   */
+  public ISession getSession(String name, boolean clientIsNew, int timeout) {
+	if(name==null) name=JavaBridge.PHPSESSION; else name="@"+name;
+	return session(name, clientIsNew, timeout);
+  }
+
+  /**
+   * @param name The session name. If name is null, the session is an internal session
+   * @param clientIsNew true if the client wants a new session
+   * @param timeout timeout in seconds. If 0 the session does not expire.
+   */
+  public ISession getSessionInternal(boolean clientIsNew, int timeout) {
+	String name=JavaBridge.INTERNAL_PHPSESSION;
+	return session(name, clientIsNew, timeout);
+  }
+		
 	
     /**
      * Return the associated context
Index: server/php/java/bridge/ThreadPool.java
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/server/php/java/bridge/ThreadPool.java,v
retrieving revision 1.9
diff -u -r1.9 ThreadPool.java
--- server/php/java/bridge/ThreadPool.java	28 Apr 2006 18:15:07 -0000	1.9
+++ server/php/java/bridge/ThreadPool.java	30 Apr 2006 16:54:57 -0000
@@ -18,18 +18,37 @@
     private int threads = 0, idles = 0, poolMaxSize;
     private LinkedList runnables = new LinkedList();
 
-    /*
+    /**
      * Threads continue to pull runnables and run them in the thread
      * environment.
      */
     public final class Delegate extends Thread {
 	private boolean isDaemon = false, terminate = false;
-	public Delegate(String n) { super(n); threads++; }
+	/** 
+	 * Create a new delegate. The thread runs until terminateDaemon() is called. 
+	 * @param name The name of the delegate. 
+	 */
+	protected Delegate(String name) { super(name); threads++; }
+	/**
+	 * Make this thread a daemon thread. A daemon is not visible but still managed by the thread pool.
+	 * @param val true or false
+	 */
 	public void setIsDaemon(boolean val) {
 	    if(isDaemon != val) threads -= (isDaemon = val) ? 1 : -1;
 	}
+	/**
+	 * Check if this thread is a daemon thread.
+	 * @return true, if the thread is a daemon, false otherwise
+	 */
 	public boolean getIsDaemon() { return isDaemon; }
-	public void terminate() { terminate = true; }
+	/**
+	 * Terminate a daemon thread.
+	 * @throws IllegalStateException, if the thread is not a daemon
+	 */
+	public void terminateDaemon() { 
+	  if(!isDaemon) throw new IllegalStateException("not a daemon");
+	  terminate = true; 
+	}
 	public void run() {
 	    try {
 		while(!terminate) getNextRunnable().run();
Index: server/php/java/servlet/FastCGIServlet.java
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/server/php/java/servlet/FastCGIServlet.java,v
retrieving revision 1.15
diff -u -r1.15 FastCGIServlet.java
--- server/php/java/servlet/FastCGIServlet.java	28 Apr 2006 18:15:07 -0000	1.15
+++ server/php/java/servlet/FastCGIServlet.java	30 Apr 2006 16:54:58 -0000
@@ -81,6 +81,7 @@
     protected String php = null; 
     protected boolean fcgiIsAvailable;
     protected boolean canStartFCGI = false;
+    protected boolean override_hosts = true;
     
     protected String startFcgiMessage() {
 	String base = context.getRealPath(cgiPathPrefix);
@@ -131,7 +132,15 @@
 	}  catch (Throwable t) {Util.printStackTrace(t);}      
     }
     public void init(ServletConfig config) throws ServletException {
+	String value;
 	super.init(config);
+    	try {
+	    value = config.getInitParameter("override_hosts");
+	    if(value==null) value="";
+	    value = value.trim();
+	    value = value.toLowerCase();
+	    if(value.equals("off") || value.equals("false")) override_hosts=false;
+	} catch (Throwable t) {Util.printStackTrace(t);}      
 
 	checkCgiBinary(config);
     }
@@ -168,7 +177,7 @@
 		    buf.append("/");
 		    buf.append(req.getRequestURI());
 		    buf.append("javabridge");
-		    this.env.put("X_JAVABRIDGE_OVERRIDE_HOSTS_REDIRECT", buf.toString());
+		    this.env.put("X_JAVABRIDGE_OVERRIDE_HOSTS_REDIRECT", override_hosts?buf.toString():"");
 	    }
 	    return success;
 	}
Index: server/php/java/servlet/PhpCGIServlet.java
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/server/php/java/servlet/PhpCGIServlet.java,v
retrieving revision 1.4
diff -u -r1.4 PhpCGIServlet.java
--- server/php/java/servlet/PhpCGIServlet.java	28 Apr 2006 18:15:07 -0000	1.4
+++ server/php/java/servlet/PhpCGIServlet.java	30 Apr 2006 16:54:58 -0000
@@ -57,7 +57,6 @@
      * servlet also consumes an instance of PhpJavaServlet.</p>
      */
     public static final int CGI_MAX_REQUESTS = 50;
-    private boolean override_hosts = true;
     private int cgi_max_requests = CGI_MAX_REQUESTS;
     private String php_fcgi_children = PHP_FCGI_CHILDREN;
     private String php_fcgi_max_requests = PHP_FCGI_MAX_REQUESTS;
@@ -119,7 +118,7 @@
 		// The value itself doesn't matter, we'll pass the real value
 		// via the (HTTP_)X_JAVABRIDGE_OVERRIDE_HOSTS header field
 		// later.
-		env.put("X_JAVABRIDGE_OVERRIDE_HOSTS", "/");
+		env.put("X_JAVABRIDGE_OVERRIDE_HOSTS", override_hosts?"/":"");
 		String[] args = new String[]{php, "-b", port};
 		File home = null;
 		try { home = ((new File(php)).getParentFile()); } catch (Exception e) {Util.printStackTrace(e);}
@@ -134,13 +133,6 @@
 	fcgiStarted = false;
     	super.init(config);
     	try {
-	    value = config.getInitParameter("override_hosts");
-	    if(value==null) value="";
-	    value = value.trim();
-	    value = value.toLowerCase();
-	    if(value.equals("off") || value.equals("false")) override_hosts=false;
-	} catch (Throwable t) {Util.printStackTrace(t);}      
-    	try {
 	    value = config.getInitParameter("max_requests");
 	    if(value!=null) {
 	        value = value.trim();
Index: server/test/HelloWorld.java
===================================================================
RCS file: /cvsroot/php-java-bridge/php-java-bridge/server/test/HelloWorld.java,v
retrieving revision 1.7
diff -u -r1.7 HelloWorld.java
--- server/test/HelloWorld.java	15 Jan 2006 21:07:31 -0000	1.7
+++ server/test/HelloWorld.java	30 Apr 2006 16:54:58 -0000
@@ -23,7 +23,7 @@
 
 	try {
 	    PhpScriptEngine engine = new PhpScriptEngine();
-	    String s = "<?php extension_loaded('java')||@dl('java.so')||@dl('php_java.dll'); ini_set('java.log_level', " +l+"); echo 'HelloWorld!\n'; java_context()->call(java_closure()) ||die('oops!');?>";
+	    String s = "<?php extension_loaded('java')||@dl('java.so')||@dl('php_java.dll'); echo 'HelloWorld!\n'; java_context()->call(java_closure()) ||die('oops!');?>";
 
 	    engine.eval(new StringReader(s));
 	    String name = (String) ((Invocable)engine).invoke("java_get_server_name", new Object[]{});
