/*-*- mode: C; tab-width:4 -*-*/
/**\file
* This is the main entry point for the java extension.
* It contains the global structures and the callbacks required for
* zend engine 1 and 2.
*
*/
/* wait */
#include <sys/types.h>
#include <sys/wait.h>
/* miscellaneous */
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include "php_java.h"
#include "php_globals.h"
#include "ext/standard/info.h"
#include "java_bridge.h"
#ifdef ZEND_ENGINE_2
#include "zend_interfaces.h"
#include "zend_exceptions.h"
#endif
EXT_DECLARE_MODULE_GLOBALS(EXT)
/**
* Holds the global configuration.
* This structure is shared by all php instances
*/
struct cfg *EXT_GLOBAL (cfg) = 0;
#ifdef __MINGW32__
static const int java_errno=0;
int *__errno (void) { return &java_errno; }
#define php_info_print_table_row(a, b, c) \
php_info_print_table_row_ex(a, "java", 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
* 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)) {
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;
return SUCCESS;
}
/**
* Called when the request terminates. Closes the connection to the
* backend, destroys the proxyenv instance.
*/
PHP_RSHUTDOWN_FUNCTION(EXT)
{
destroy_cloned_cfg(TSRMLS_C);
EXT_GLOBAL(destroy_channel)(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;
JG(is_closed)=1;
return SUCCESS;
}
static void last_exception_get(proxyenv *jenv, zval**return_value)
{
(*jenv)->writeInvokeBegin(jenv, 0, "lastException", 0, 'P', *return_value);
(*jenv)->writeInvokeEnd(jenv);
}
/**
* Proto: object java_last_exception_get(void)
*
* Get last Java exception
* \deprecated Use PHP5 try/catch instead.
*/
EXT_FUNCTION(EXT_GLOBAL(last_exception_get))
{
proxyenv *jenv;
if (ZEND_NUM_ARGS()!=0) WRONG_PARAM_COUNT;
jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C);
if(!jenv) {RETURN_NULL();}
last_exception_get(jenv, &return_value);
}
static void last_exception_clear(proxyenv*jenv, zval**return_value) {
(*jenv)->writeInvokeBegin(jenv, 0, "lastException", 0, 'P', *return_value);
(*jenv)->writeObject(jenv, 0);
(*jenv)->writeInvokeEnd(jenv);
}
/**
* Proto: void java_last_exception_clear(void)
*
* Clear last java extension.
* \deprecated Use PHP5 try/catch instead.
*/
EXT_FUNCTION(EXT_GLOBAL(last_exception_clear))
{
proxyenv *jenv;
if (ZEND_NUM_ARGS()!=0) WRONG_PARAM_COUNT;
jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C);
if(!jenv) {RETURN_NULL();}
last_exception_clear(jenv, &return_value);
}
/**
* Proto: void java_set_file_encoding(string)
*
* Set the java file encoding, for example UTF-8 or ASCII. Needed
* because php does not support unicode. All string to byte array
* conversions use this encoding. Example: \code
* java_set_file_encoding("ISO-8859-1"); \endcode
*/
EXT_FUNCTION(EXT_GLOBAL(set_file_encoding))
{
zval **enc;
proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C);
if(!jenv) {RETURN_NULL();}
if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &enc) == FAILURE)
WRONG_PARAM_COUNT;
convert_to_string_ex(enc);
(*jenv)->writeInvokeBegin(jenv, 0, "setFileEncoding", 0, 'I', return_value);
(*jenv)->writeString(jenv, Z_STRVAL_PP(enc), Z_STRLEN_PP(enc));
(*jenv)->writeInvokeEnd(jenv);
}
static void require(INTERNAL_FUNCTION_PARAMETERS) {
static const char ext_dir[] = "extension_dir";
char *ext = php_ini_string((char*)ext_dir, sizeof ext_dir, 0);
zval **path;
proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C);
if(!jenv) {RETURN_NULL();}
if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &path) == FAILURE)
WRONG_PARAM_COUNT;
convert_to_string_ex(path);
#if EXTENSION == JAVA
(*jenv)->writeInvokeBegin(jenv, 0, "setJarLibraryPath", 0, 'I', return_value);
#else
(*jenv)->writeInvokeBegin(jenv, 0, "setLibraryPath", 0, 'I', return_value);
#endif
(*jenv)->writeString(jenv, Z_STRVAL_PP(path), Z_STRLEN_PP(path));
(*jenv)->writeString(jenv, ext, strlen(ext));
(*jenv)->writeInvokeEnd(jenv);
}
/**
* Proto: void java_require(string path) or java_set_library_path(string path)
*
* Set the library path. Example:
* \code
* java_require("foo.jar;bar.jar");
* \endcode
*
* The .jar files should be stored in /usr/share/java or
* extension_dir/lib one of its sub-directories. However, it is also
* possible to fetch .jar files from a remote server, for example:
* \code
* java_require("http://php-java-bridge.sf.net/kawa.jar;...");
* \endcode
*
* Note that the classloader isolates the loaded libraries: When you
* 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
* clear the loader cache and load your classes and the library in one
* java_require() call.
*/
EXT_FUNCTION(EXT_GLOBAL(require))
{
require(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/**
* Proto: bool java_instanceof(object object, object clazz)
*
* Tests if object is an instance of clazz.
* Example:
* \code
* return($o instanceof Java && $c instanceof Java && java_instanceof($o, $c));
* \endcode
*/
EXT_FUNCTION(EXT_GLOBAL(instanceof))
{
zval **pobj, **pclass;
long obj, class;
proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C);
if(!jenv) {RETURN_NULL();}
if (ZEND_NUM_ARGS()!=2 || zend_get_parameters_ex(2, &pobj, &pclass) == FAILURE)
WRONG_PARAM_COUNT;
convert_to_object_ex(pobj);
convert_to_object_ex(pclass);
obj = 0;
EXT_GLOBAL(get_jobject_from_object)(*pobj, &obj TSRMLS_CC);
if(!obj) {
zend_error(E_ERROR, "Argument #1 for %s() must be a "/**/EXT_NAME()/**/" object", get_active_function_name(TSRMLS_C));
return;
}
class = 0;
EXT_GLOBAL(get_jobject_from_object)(*pclass, &class TSRMLS_CC);
if(!class) {
zend_error(E_ERROR, "Argument #2 for %s() must be a "/**/EXT_NAME()/**/" object", get_active_function_name(TSRMLS_C));
return;
}
(*jenv)->writeInvokeBegin(jenv, 0, "InstanceOf", 0, 'I', return_value);
(*jenv)->writeObject(jenv, obj);
(*jenv)->writeObject(jenv, class);
(*jenv)->writeInvokeEnd(jenv);
}
static long session_get_default_lifetime() {
static const char session_max_lifetime[]="session.gc_maxlifetime";
return zend_ini_long((char*)session_max_lifetime, sizeof(session_max_lifetime), 0);
}
static void session(INTERNAL_FUNCTION_PARAMETERS)
{
proxyenv *jenv;
zval **session=0, **is_new=0;
int argc=ZEND_NUM_ARGS();
if (argc>2 || zend_get_parameters_ex(argc, &session, &is_new) == FAILURE)
WRONG_PARAM_COUNT;
jenv=EXT_GLOBAL(connect_to_server)(TSRMLS_C);
if(!jenv) RETURN_NULL();
assert(EXT_GLOBAL(cfg)->is_cgi_servlet && (*jenv)->servlet_ctx ||!EXT_GLOBAL(cfg)->is_cgi_servlet);
EXT_GLOBAL(check_context) (jenv TSRMLS_CC); /* re-direct if no
context was found */
(*jenv)->writeInvokeBegin(jenv, 0, "getSession", 0, 'I', return_value);
if(argc>0 && Z_TYPE_PP(session)!=IS_NULL) {
convert_to_string_ex(session);
(*jenv)->writeString(jenv, Z_STRVAL_PP(session), Z_STRLEN_PP(session));
} else {
(*jenv)->writeObject(jenv, 0);
}
(*jenv)->writeBoolean(jenv, (argc<2||Z_TYPE_PP(is_new)==IS_NULL)?0:Z_BVAL_PP(is_new));
(*jenv)->writeLong(jenv, session_get_default_lifetime()); // session.gc_maxlifetime
(*jenv)->writeInvokeEnd(jenv);
}
/**
* Proto: object java_session([string], [bool]) or object java_get_session([string], [bool])
*
* Return a session handle. When java_session() is called without
* arguments, the session is shared with java.
* Example:
* \code
* java_get_session()->put("key", new Java("java.lang.Object"));
* [...]
* \endcode
* The java components (jsp, servlets) can retrieve the value, for
* example with:
* \code getSession().getAttribute("key"); \endcode
*
* When java_get_session() is called with a session handle, the session
* is not shared with java and no cookies are set. Example:
* \code
* java_get_session("myPrivateApplicationStore")->put("key", "value");
* \endcode
*
* When java_get_session() is called with a second argument set to true,
* a new session is allocated, the old session is destroyed if necessary.
* Example:
* \code
* java_get_session(null, true)->put("key", "val");
* \endcode.
* @see get_context()
*/
EXT_FUNCTION(EXT_GLOBAL(get_session))
{
session(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
static void context(INTERNAL_FUNCTION_PARAMETERS)
{
proxyenv *jenv;
int argc=ZEND_NUM_ARGS();
if (argc!=0)
WRONG_PARAM_COUNT;
jenv=EXT_GLOBAL(connect_to_server)(TSRMLS_C);
if(!jenv) RETURN_NULL();
assert(EXT_GLOBAL(cfg)->is_cgi_servlet && (*jenv)->servlet_ctx ||!EXT_GLOBAL(cfg)->is_cgi_servlet);
EXT_GLOBAL(check_context) (jenv TSRMLS_CC); /* re-direct if no
context was found */
(*jenv)->writeInvokeBegin(jenv, 0, "getContext", 0, 'I', return_value);
(*jenv)->writeInvokeEnd(jenv);
}
/**
* Proto: object java_context(void) or object java_get_context(void)
*
* Returns the jsr223 script context handle.
*
* Example which closes over the current environment and pass it back to java:
* \code
* java_get_context()->call(java_closure()) || die "Script should be called from java";
* \endcode
*
* It is possible to access implicit web objects (the session, the
* application store etc.) from the context. Please see the JSR223
* documentation or for details. Example:
* \code
* java_get_context()->getHttpServletRequest();
* \endcode
* @see java_get_session()
*/
EXT_FUNCTION(EXT_GLOBAL(get_context))
{
context(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/**
* 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:
* \code
* $backend = java_get_server_name();
* if(!$backend) wakeup_administrator("backend not running");
* echo "Connected to the backend: $backend\n";
* \endcode
*/
EXT_FUNCTION(EXT_GLOBAL(get_server_name))
{
proxyenv *jenv;
if (ZEND_NUM_ARGS()!=0) WRONG_PARAM_COUNT;
jenv = EXT_GLOBAL(try_connect_to_server)(TSRMLS_C);
if(jenv && (*jenv)->server_name) {
RETURN_STRING((*jenv)->server_name, 1);
}
RETURN_NULL();
}
/**
* Proto: void java_reset(void);
*
* Tries to reset the backent to
* its initial state. If the call succeeds, all session handles and
* caches are gone.
*
* Example:
* \code echo "Resetting backend to initial state\n";
* java_reset();
* \endcode
*
* This procedure does nothing when the backend runs
* in a servlet environment or an application server.
*/
EXT_FUNCTION(EXT_GLOBAL(reset))
{
proxyenv *jenv;
if (ZEND_NUM_ARGS()!=0) WRONG_PARAM_COUNT;
jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C);
if(!jenv) RETURN_NULL();
(*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()/**/" session variables and all caches are gone.", 18);
}
static void values(INTERNAL_FUNCTION_PARAMETERS)
{
proxyenv *jenv;
zval **pobj;
long obj;
jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C);
if(!jenv) RETURN_NULL();
if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &pobj) == FAILURE)
WRONG_PARAM_COUNT;
#ifdef ZEND_ENGINE_2
convert_to_object_ex(pobj);
obj = 0;
EXT_GLOBAL(get_jobject_from_object)(*pobj, &obj TSRMLS_CC);
if(!obj) {
zend_error(E_ERROR, "Argument for %s() must be a "/**/EXT_NAME()/**/" object", get_active_function_name(TSRMLS_C));
RETURN_NULL();
}
(*jenv)->writeInvokeBegin(jenv, 0, "getValues", 0, 'I', return_value);
(*jenv)->writeObject(jenv, obj);
(*jenv)->writeInvokeEnd(jenv);
#else
*return_value = **pobj;
zval_copy_ctor(return_value);
#endif
}
static const char warn_session[] =
"Probably the object has been destroyed already by the java_rshutdown() method -- have you loaded the \
session module before the java module? Use \
java_session(session_id())->set(key,val) instead of the \
\"$_SESSION[key]=val\" syntax, if you don't want to depend on the \
session module or if you cannot guarantee that the session module's \
rshutdown function is called before the zend objects store is \
destroyed and before the PHP/Java Bridge rshutdown function is called. \n\
If \"session_write_close();\" at the end of your script fixes this problem, \
please report this PHP bug to the PHP release team.";
static const char identity[] = "serialID";
static void serialize(INTERNAL_FUNCTION_PARAMETERS)
{
long obj;
zval *handle, *id;
proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C);
if(!jenv) {
php_error(E_WARNING, EXT_NAME()/**/" cannot be serialized. %s", warn_session);
RETURN_NULL();
}
EXT_GLOBAL(get_jobject_from_object)(getThis(), &obj TSRMLS_CC);
if(!obj) {
/* set a breakpoint in java_bridge.c destroy_object, in rshutdown
and get_jobject_from_object */
php_error(E_WARNING, EXT_NAME()/**/" cannot be serialized. %s", warn_session);
RETURN_NULL();
}
MAKE_STD_ZVAL(handle);
ZVAL_NULL(handle);
(*jenv)->writeInvokeBegin(jenv, 0, "serialize", 0, 'I', handle);
(*jenv)->writeObject(jenv, obj);
(*jenv)->writeLong(jenv, session_get_default_lifetime()); // session.gc_maxlifetime
(*jenv)->writeInvokeEnd(jenv);
zend_hash_update(Z_OBJPROP_P(getThis()), (char*)identity, sizeof identity, &handle, sizeof(pval *), NULL);
/* Return the field that should be serialized ("serialID") */
array_init(return_value);
INIT_PZVAL(return_value);
MAKE_STD_ZVAL(id);
Z_TYPE_P(id)=IS_STRING;
Z_STRLEN_P(id)=sizeof(identity)-1;
Z_STRVAL_P(id)=estrdup(identity);
zend_hash_index_update(Z_ARRVAL_P(return_value), 0, &id, sizeof(pval*), NULL);
}
static void deserialize(INTERNAL_FUNCTION_PARAMETERS)
{
zval *handle, **id;
int err;
proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C);
if(!jenv) {
php_error(E_ERROR, EXT_NAME()/**/" cannot be de-serialized. %s", warn_session);
}
err = zend_hash_find(Z_OBJPROP_P(getThis()), (char*)identity, sizeof identity, (void**)&id);
if(FAILURE==err) {
/* set a breakpoint in java_bridge.c destroy_object, in rshutdown
and get_jobject_from_object */
php_error(E_WARNING, EXT_NAME()/**/" cannot be deserialized. %s", warn_session);
}
MAKE_STD_ZVAL(handle);
ZVAL_NULL(handle);
(*jenv)->writeInvokeBegin(jenv, 0, "deserialize", 0, 'I', handle);
(*jenv)->writeString(jenv, Z_STRVAL_PP(id), Z_STRLEN_PP(id));
(*jenv)->writeLong(jenv, session_get_default_lifetime()); // use session.gc_maxlifetime
(*jenv)->writeInvokeEnd(jenv);
if(Z_TYPE_P(handle)!=IS_LONG) {
#ifndef ZEND_ENGINE_2
php_error(E_WARNING, EXT_NAME()/**/" cannot be deserialized, session expired.");
#endif
ZVAL_NULL(getThis());
} else {
#ifndef ZEND_ENGINE_2
zend_hash_index_update(Z_OBJPROP_P(getThis()), 0, &handle, sizeof(pval *), NULL);
#else
EXT_GLOBAL(store_jobject)(getThis(), Z_LVAL_P(handle) TSRMLS_CC);
#endif
}
RETURN_NULL();
}
#ifndef ZEND_ENGINE_2
EXT_FUNCTION(EXT_GLOBAL(__sleep))
{
serialize(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
EXT_FUNCTION(EXT_GLOBAL(__wakeup))
{
deserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
#endif
/** Proto: array java_values(object ob) or array java_get_values(object ob)
*
* Fetches the object into a php array. ob must be a java array or it
* must implement java.util.Map or java.util.Collection. Please make sure that the java array, Map or Collection does not exceed php's memory limit. Example:
* \code
* print_r(java_get_values($sys->getProperties()));
* \endcode
*/
EXT_FUNCTION(EXT_GLOBAL(get_values))
{
values(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/**
* Proto: object java_closure([object],[array|string],[object]) or object java_get_closure([object],[array|string],[object])
*
* Closes over the php environment and packages it up as a java
* class. Example:
* \code
* function toString() {return "helloWorld";};
* $object = java_get_closure();
* echo (string)$object;
* \endcode
*
* When a php instance is supplied as a argument, that environment will be used
* instead. When a string or key/value map is supplied as a second argument,
* the java procedure names are mapped to the php procedure names. Example:
* \code
* function hello() {return "hello";};
* echo (string)java_get_closure(null, "hello");
* \endcode
*
* When an array of java interfaces is supplied as a third argument,
* the environment must implement these interfaces.
* Example:
* \code
* class Listener {
* function actionPerformed($actionEvent) {
* ...
* }
* }
* function getListener() {
* return java_get_closure(new Listener(), null, array(new Java("java.awt.event.ActionListener")));
* }
* \endcode
*/
EXT_FUNCTION(EXT_GLOBAL(get_closure))
{
char *string_key;
ulong num_key;
zval **pobj, **pfkt, **pclass, **val;
long class = 0;
int key_type;
proxyenv *jenv;
int argc = ZEND_NUM_ARGS();
if (argc>3 || zend_get_parameters_ex(argc, &pobj, &pfkt, &pclass) == FAILURE)
WRONG_PARAM_COUNT;
jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C);
if(!jenv) RETURN_NULL();
if (argc>0 && *pobj && Z_TYPE_PP(pobj) == IS_OBJECT) {
zval_add_ref(pobj);
}
(*jenv)->writeInvokeBegin(jenv, 0, "makeClosure", 0, 'I', return_value);
(*jenv)->writeLong(jenv, (argc==0||Z_TYPE_PP(pobj)==IS_NULL)?0:(long)*pobj);
/* fname -> cname Map */
if(argc>1) {
if (Z_TYPE_PP(pfkt) == IS_ARRAY) {
(*jenv)->writeCompositeBegin_h(jenv);
zend_hash_internal_pointer_reset(Z_ARRVAL_PP(pfkt));
while ((key_type = zend_hash_get_current_key(Z_ARRVAL_PP(pfkt), &string_key, &num_key, 1)) != HASH_KEY_NON_EXISTANT) {
if ((zend_hash_get_current_data(Z_ARRVAL_PP(pfkt), (void**)&val) == SUCCESS)) {
if(Z_TYPE_PP(val) == IS_STRING && key_type==HASH_KEY_IS_STRING) {
size_t len = strlen(string_key);
(*jenv)->writePairBegin_s(jenv, string_key, len);
(*jenv)->writeString(jenv, Z_STRVAL_PP(val), Z_STRLEN_PP(val));
(*jenv)->writePairEnd(jenv);
} else {
zend_error(E_ERROR, "Argument #2 for %s() must be null, a string, or a map of java => php function names.", get_active_function_name(TSRMLS_C));
}
}
zend_hash_move_forward(Z_ARRVAL_PP(pfkt));
}
(*jenv)->writeCompositeEnd(jenv);
} else if (Z_TYPE_PP(pfkt) == IS_STRING) {
(*jenv)->writeString(jenv, Z_STRVAL_PP(pfkt), Z_STRLEN_PP(pfkt));
} else {
(*jenv)->writeCompositeBegin_h(jenv);
(*jenv)->writeCompositeEnd(jenv);
}
}
/* interfaces */
if(argc>2) {
(*jenv)->writeCompositeBegin_a(jenv);
if(Z_TYPE_PP(pclass) == IS_ARRAY) {
zend_hash_internal_pointer_reset(Z_ARRVAL_PP(pclass));
while ((key_type = zend_hash_get_current_data(Z_ARRVAL_PP(pclass), (void**)&val)) == SUCCESS) {
EXT_GLOBAL(get_jobject_from_object)(*val, &class TSRMLS_CC);
if(class) {
(*jenv)->writePairBegin(jenv);
(*jenv)->writeObject(jenv, class);
(*jenv)->writePairEnd(jenv);
} else {
zend_error(E_ERROR, "Argument #3 for %s() must be a "/**/EXT_NAME()/**/" interface or an array of interfaces.", get_active_function_name(TSRMLS_C));
}
zend_hash_move_forward(Z_ARRVAL_PP(pclass));
}
} else {
EXT_GLOBAL(get_jobject_from_object)(*pclass, &class TSRMLS_CC);
if(class) {
(*jenv)->writePairBegin(jenv);
(*jenv)->writeObject(jenv, class);
(*jenv)->writePairEnd(jenv);
} else {
zend_error(E_ERROR, "Argument #3 for %s() must be a "/**/EXT_NAME()/**/" interface or an array of interfaces.", get_active_function_name(TSRMLS_C));
}
}
(*jenv)->writeCompositeEnd(jenv);
}
(*jenv)->writeInvokeEnd(jenv);
}
/**
* Only for internal use.
*/
EXT_FUNCTION(EXT_GLOBAL(exception_handler))
{
zval **pobj;
if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &pobj) == FAILURE) WRONG_PARAM_COUNT;
MAKE_STD_ZVAL(JG(exception));
*JG(exception)=**pobj;
zval_copy_ctor(JG(exception));
RETURN_NULL();
}
/**
* Only for internal use
*/
static void check_php4_exception(TSRMLS_D) {
#ifndef ZEND_ENGINE_2
last_exception_get(JG(jenv), &JG(exception));
#endif
}
static int allocate_php4_exception(TSRMLS_D) {
#ifndef ZEND_ENGINE_2
MAKE_STD_ZVAL(JG(exception));
ZVAL_NULL(JG(exception));
last_exception_clear(JG(jenv), &JG(exception));
#endif
return 1;
}
static void call_with_handler(char*handler, const char*name TSRMLS_DC) {
if(allocate_php4_exception(TSRMLS_C))
if(zend_eval_string((char*)handler, *JG(retval_ptr), (char*)name TSRMLS_CC)!=SUCCESS) {
php_error(E_WARNING, "php_mod_"/**/EXT_NAME()/**/"(%d): Could not call user function: %s.", 22, Z_STRVAL_P(JG(func)));
}
}
static void call_with_params(int count, zval ***func_params TSRMLS_DC) {
if(allocate_php4_exception(TSRMLS_C)) /* checked and destroyed in client. handle_exception() */
if (call_user_function_ex(0, JG(object), JG(func), JG(retval_ptr), count, func_params, 0, NULL TSRMLS_CC) != SUCCESS) {
php_error(E_WARNING, "php_mod_"/**/EXT_NAME()/**/"(%d): Could not call user function: %s.", 23, Z_STRVAL_P(JG(func)));
}
}
/**
* Only for internal use.
*/
EXT_FUNCTION(EXT_GLOBAL(call_with_exception_handler))
{
zval ***func_params;
HashTable *func_params_ht;
int count, current;
if (ZEND_NUM_ARGS()==1) {
*return_value=*JG(func_params);
zval_copy_ctor(return_value);
return;
}
/* for functions in the global environment */
if(!*JG(object)) {
static const char name[] = "call_global_func_with_exception_handler";
static const char call_user_funcH[] = "call_user_func_array('";
static const char call_user_funcT[] = "',"/**/EXT_NAME()/**/"_call_with_exception_handler(true));";
char *handler=emalloc(sizeof(call_user_funcH)-1+Z_STRLEN_P(JG(func))+sizeof(call_user_funcT));
assert(handler); if(!handler) exit(9);
strcpy(handler, call_user_funcH);
strcat(handler, Z_STRVAL_P(JG(func)));
strcat(handler, call_user_funcT);
MAKE_STD_ZVAL(*JG(retval_ptr)); ZVAL_NULL(*JG(retval_ptr));
call_with_handler(handler, name TSRMLS_CC);
check_php4_exception(TSRMLS_C);
efree(handler);
RETURN_NULL();
}
/* for methods */
current=0;
func_params_ht = Z_ARRVAL_P(JG(func_params));
count = zend_hash_num_elements(func_params_ht);
func_params = safe_emalloc(sizeof(zval **), count, 0);
for (zend_hash_internal_pointer_reset(func_params_ht);
zend_hash_get_current_data(func_params_ht, (void **) &func_params[current]) == SUCCESS;
zend_hash_move_forward(func_params_ht)
) {
current++;
}
call_with_params(count, func_params TSRMLS_CC);
check_php4_exception(TSRMLS_C);
efree(func_params);
RETURN_NULL();
}
/**
* Proto: void java_inspect(object);
*
* Returns the contents (public fields, public methods, public
* classes) of object as a string.
* Example:
* \code
* echo java_inspect(java_get_context());
* \endcode
*/
EXT_FUNCTION(EXT_GLOBAL(inspect)) {
zval **pobj;
long obj;
proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C);
if(!jenv) {RETURN_NULL();}
if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &pobj) == FAILURE)
WRONG_PARAM_COUNT;
convert_to_object_ex(pobj);
obj = 0;
EXT_GLOBAL(get_jobject_from_object)(*pobj, &obj TSRMLS_CC);
if(!obj) {
zend_error(E_ERROR, "Argument for %s() must be a "/**/EXT_NAME()/**/" object", get_active_function_name(TSRMLS_C));
return;
}
(*jenv)->writeInvokeBegin(jenv, 0, "inspect", 0, 'I', return_value);
(*jenv)->writeObject(jenv, obj);
(*jenv)->writeInvokeEnd(jenv);
}
function_entry EXT_GLOBAL(functions)[] = {
EXT_FE(EXT_GLOBAL(last_exception_get), NULL)
EXT_FE(EXT_GLOBAL(last_exception_clear), NULL)
EXT_FE(EXT_GLOBAL(set_file_encoding), NULL)
EXT_FE(EXT_GLOBAL(instanceof), NULL)
EXT_FE(EXT_GLOBAL(require), NULL)
EXT_FALIAS(EXT_GLOBAL(set_library_path), EXT_GLOBAL(require), NULL)
EXT_FE(EXT_GLOBAL(get_session), NULL)
EXT_FALIAS(EXT_GLOBAL(session), EXT_GLOBAL(get_session), NULL)
EXT_FE(EXT_GLOBAL(get_context), NULL)
EXT_FALIAS(EXT_GLOBAL(context), EXT_GLOBAL(get_context), NULL)
EXT_FE(EXT_GLOBAL(get_server_name), NULL)
EXT_FALIAS(EXT_GLOBAL(server_name), EXT_GLOBAL(get_server_name), NULL)
EXT_FE(EXT_GLOBAL(get_values), NULL)
EXT_FALIAS(EXT_GLOBAL(values), EXT_GLOBAL(get_values), NULL)
EXT_FE(EXT_GLOBAL(get_closure), NULL)
EXT_FALIAS(EXT_GLOBAL(closure), EXT_GLOBAL(get_closure), NULL)
EXT_FE(EXT_GLOBAL(call_with_exception_handler), NULL)
EXT_FE(EXT_GLOBAL(exception_handler), NULL)
EXT_FE(EXT_GLOBAL(inspect), NULL)
EXT_FE(EXT_GLOBAL(reset), NULL)
{NULL, NULL, NULL}
};
zend_module_entry EXT_GLOBAL(module_entry) = {
STANDARD_MODULE_HEADER,
EXT_NAME(),
EXT_GLOBAL(functions),
EXT_MINIT(EXT),
EXT_MSHUTDOWN(EXT),
EXT_RINIT(EXT),
EXT_RSHUTDOWN(EXT),
EXT_MINFO(EXT),
NO_VERSION_YET,
STANDARD_MODULE_PROPERTIES
};
#if defined(COMPILE_DL_JAVA) || defined(COMPILE_DL_MONO)
EXT_GET_MODULE(EXT)
#endif
/**
* Holds the flags set/unset for all java ini entries
*/
int EXT_GLOBAL(ini_updated);
/**
* The options set by the user.
*/
int EXT_GLOBAL(ini_user);
/**
* The options which carry a value.
*/
int EXT_GLOBAL(ini_set);
/**
* Represents the java class struct
*/
zend_class_entry *EXT_GLOBAL(class_entry);
/**
* Represents the java class array struct
*/
zend_class_entry *EXT_GLOBAL(array_entry);
/**
* Represents the java_class class struct
*/
zend_class_entry *EXT_GLOBAL(class_class_entry);
/**
* Represents the javaclass class struct
*/
zend_class_entry *EXT_GLOBAL(class_class_entry_jsr);
/**
* Represents the javaexception class struct
*/
zend_class_entry *EXT_GLOBAL(exception_class_entry);
#ifdef ZEND_ENGINE_2
/**
* The object handlers, see create_object.
*/
zend_object_handlers EXT_GLOBAL(handlers);
#endif
static const char on[]="On";
static const char on2[]="1";
static const char off[]="Off";
static PHP_INI_MH(OnIniWrapper)
{
if (new_value) {
if((EXT_GLOBAL (ini_set) &U_WRAPPER)) free(EXT_GLOBAL(cfg)->wrapper);
EXT_GLOBAL(cfg)->wrapper=strdup(new_value);
assert(EXT_GLOBAL(cfg)->wrapper); if(!EXT_GLOBAL(cfg)->wrapper) exit(6);
EXT_GLOBAL(ini_updated)|=U_WRAPPER;
}
return SUCCESS;
}
static PHP_INI_MH(OnIniHosts)
{
if (new_value) {
if((EXT_GLOBAL (ini_set) &U_HOSTS)) free(EXT_GLOBAL(cfg)->hosts);
EXT_GLOBAL(cfg)->hosts=strdup(new_value);
assert(EXT_GLOBAL(cfg)->hosts); if(!EXT_GLOBAL(cfg)->hosts) exit(6);
EXT_GLOBAL(ini_updated)|=U_HOSTS;
}
return SUCCESS;
}
static PHP_INI_MH(OnIniServlet)
{
if (new_value) {
if((EXT_GLOBAL (ini_set) &U_SERVLET)) free(EXT_GLOBAL(cfg)->servlet);
if(!strncasecmp(on, new_value, 2) || !strncasecmp(on2, new_value, 1))
EXT_GLOBAL(cfg)->servlet=strdup(DEFAULT_SERVLET);
else
EXT_GLOBAL(cfg)->servlet=strdup(new_value);
assert(EXT_GLOBAL(cfg)->servlet); if(!EXT_GLOBAL(cfg)->servlet) exit(6);
EXT_GLOBAL(ini_updated)|=U_SERVLET;
}
return SUCCESS;
}
static PHP_INI_MH(OnIniSockname)
{
if (new_value) {
if((EXT_GLOBAL (ini_set) &U_SOCKNAME)) free(EXT_GLOBAL(cfg)->sockname);
EXT_GLOBAL(cfg)->sockname=strdup(new_value);
assert(EXT_GLOBAL(cfg)->sockname); if(!EXT_GLOBAL(cfg)->sockname) exit(6);
EXT_GLOBAL(ini_updated)|=U_SOCKNAME;
}
return SUCCESS;
}
static PHP_INI_MH(OnIniClassPath)
{
if (new_value) {
if((EXT_GLOBAL (ini_set) &U_CLASSPATH)) free(EXT_GLOBAL(cfg)->classpath);
EXT_GLOBAL(cfg)->classpath =strdup(new_value);
assert(EXT_GLOBAL(cfg)->classpath); if(!EXT_GLOBAL(cfg)->classpath) exit(6);
EXT_GLOBAL(ini_updated)|=U_CLASSPATH;
}
return SUCCESS;
}
static PHP_INI_MH(OnIniLibPath)
{
if (new_value) {
if((EXT_GLOBAL (ini_set) &U_LIBRARY_PATH)) free(EXT_GLOBAL(cfg)->ld_library_path);
EXT_GLOBAL(cfg)->ld_library_path = strdup(new_value);
assert(EXT_GLOBAL(cfg)->ld_library_path); if(!EXT_GLOBAL(cfg)->ld_library_path) exit(6);
EXT_GLOBAL(ini_updated)|=U_LIBRARY_PATH;
}
return SUCCESS;
}
static PHP_INI_MH(OnIniJava)
{
if (new_value) {
if((EXT_GLOBAL (ini_set) &U_JAVA)) free(EXT_GLOBAL(cfg)->vm);
EXT_GLOBAL(cfg)->vm = strdup(new_value);
assert(EXT_GLOBAL(cfg)->vm); if(!EXT_GLOBAL(cfg)->vm) exit(6);
EXT_GLOBAL(ini_updated)|=U_JAVA;
}
return SUCCESS;
}
static PHP_INI_MH(OnIniJavaHome)
{
if (new_value) {
if((EXT_GLOBAL (ini_set) &U_JAVA_HOME)) free(EXT_GLOBAL(cfg)->vm_home);
EXT_GLOBAL(cfg)->vm_home = strdup(new_value);
assert(EXT_GLOBAL(cfg)->vm_home); if(!EXT_GLOBAL(cfg)->vm_home) exit(6);
EXT_GLOBAL(ini_updated)|=U_JAVA_HOME;
}
return SUCCESS;
}
static PHP_INI_MH(OnIniLogLevel)
{
if (new_value) {
if((EXT_GLOBAL (ini_set) &U_LOGLEVEL)) free(EXT_GLOBAL(cfg)->logLevel);
EXT_GLOBAL(cfg)->logLevel = strdup(new_value);
assert(EXT_GLOBAL(cfg)->logLevel); if(!EXT_GLOBAL(cfg)->logLevel) exit(6);
EXT_GLOBAL(cfg)->logLevel_val=atoi(EXT_GLOBAL(cfg)->logLevel);
EXT_GLOBAL(ini_updated)|=U_LOGLEVEL;
}
return SUCCESS;
}
static PHP_INI_MH(OnIniLogFile)
{
if (new_value) {
if((EXT_GLOBAL (ini_set) &U_LOGFILE)) free(EXT_GLOBAL(cfg)->logFile);
EXT_GLOBAL(cfg)->logFile = strdup(new_value);
assert(EXT_GLOBAL(cfg)->logFile); if(!EXT_GLOBAL(cfg)->logFile) exit(6);
EXT_GLOBAL(ini_updated)|=U_LOGFILE;
}
return SUCCESS;
}
PHP_INI_BEGIN()
PHP_INI_ENTRY(EXT_NAME()/**/".servlet", NULL, PHP_INI_SYSTEM, OnIniServlet)
PHP_INI_ENTRY(EXT_NAME()/**/".socketname", NULL, PHP_INI_SYSTEM, OnIniSockname)
PHP_INI_ENTRY(EXT_NAME()/**/".hosts", NULL, PHP_INI_SYSTEM, OnIniHosts)
PHP_INI_ENTRY(EXT_NAME()/**/".wrapper", NULL, PHP_INI_SYSTEM, OnIniWrapper)
PHP_INI_ENTRY(EXT_NAME()/**/".classpath", NULL, PHP_INI_SYSTEM, OnIniClassPath)
PHP_INI_ENTRY(EXT_NAME()/**/".libpath", NULL, PHP_INI_SYSTEM, OnIniLibPath)
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_file", NULL, PHP_INI_SYSTEM, OnIniLogFile)
PHP_INI_END()
/* vm_alloc_globals_ctor(zend_vm_globals *vm_globals) */
static void EXT_GLOBAL(alloc_globals_ctor)(EXT_GLOBAL_EX(zend_,globals,_) *EXT_GLOBAL(globals) TSRMLS_DC)
{
EXT_GLOBAL(globals)->jenv=0;
EXT_GLOBAL(globals)->is_closed=-1;
EXT_GLOBAL(globals)->ini_user=0;
EXT_GLOBAL(globals)->hosts=0;
EXT_GLOBAL(globals)->servlet=0;
}
#ifdef ZEND_ENGINE_2
/**
* Proto: object Java::Java (string classname [, string argument1, .\ .\ .\ ]) or object Java::java_exception (string classname [, string argument1, .\ .\ .\ ]) or object Java::JavaException (string classname [, string argument1, .\ .\ .\ ]);
*
* Java constructor. Example:
* \code
* $object = new Java("java.lang.String", "hello world");
* echo (string)$object;
* \endcode
* \code
* $ex = new JavaException("java.lang.NullPointerException");
* throw $ex;
*
* \endcode
*/
EXT_FUNCTION(EXT_GLOBAL(construct))
{
zval **argv;
int argc = ZEND_NUM_ARGS();
argv = (zval **) safe_emalloc(sizeof(zval *), argc, 0);
if (zend_get_parameters_array(ht, argc, argv) == FAILURE) {
php_error(E_ERROR, "Couldn't fetch arguments into array.");
RETURN_NULL();
}
if(argc<1 || Z_TYPE_P(argv[0])!=IS_STRING) WRONG_PARAM_COUNT;
EXT_GLOBAL(call_function_handler)(INTERNAL_FUNCTION_PARAM_PASSTHRU,
EXT_NAME(), CONSTRUCTOR, 1,
getThis(),
argc, argv);
efree(argv);
}
/**
* Proto: object Java::JavaClass ( string classname) or object java::java_class ( string classname);
*
* References a java class. Example:
* \code
* $Object = new JavaClass("java.lang.Object");
* $object = $Object->newInstance();
* \endcode
* \code
* $Thread = new JavaClass("java.lang.Thread");
* $Thread->sleep(1000);
* \endcode
*/
#if EXTENSION == JAVA
EXT_METHOD(EXT, java_class)
#elif EXTENSION == MONO
EXT_METHOD(EXT, mono_class)
#endif
{
zval **argv;
int argc = ZEND_NUM_ARGS();
argv = (zval **) safe_emalloc(sizeof(zval *), argc, 0);
if (zend_get_parameters_array(ht, argc, argv) == FAILURE) {
php_error(E_ERROR, "Couldn't fetch arguments into array.");
RETURN_NULL();
}
if(argc<1 || Z_TYPE_P(argv[0])!=IS_STRING) WRONG_PARAM_COUNT;
EXT_GLOBAL(call_function_handler)(INTERNAL_FUNCTION_PARAM_PASSTHRU,
EXT_NAME(), CONSTRUCTOR, 0,
getThis(),
argc, argv);
efree(argv);
}
/**
* Proto: mixed Java::__call ( string procedure_name [, array arguments ])
*
* Calls a Java procedure
* Example:
* \code
* # The JPersistenceAdapter makes it possible to serialize java values.
* #
* # Example:
* # $v=new JPersistenceAdapter(new Java("java.lang.StringBuffer", "hello"));
* # $id=serialize($v);
* # $file=fopen("file.out","w");
* # fwrite($file, $id);
* # fclose($file);
* #
*
* class JPersistenceProxy {
* var $java;
* var $serialID;
*
* function __construct($java){
* $this->java=$java;
* $this->serialID;
* }
* function __sleep() {
* $buf = new Java("java.io.ByteArrayOutputStream");
* $out = new Java("java.io.ObjectOutputStream", $buf);
* $out->writeObject($this->java);
* $out->close();
* $this->serialID = base64_encode((string)$buf->toByteArray());
* return array("serialID");
* }
* function __wakeup() {
* $buf = new Java("java.io.ByteArrayInputStream",base64_decode($this->serialID));
* $in = new Java("java.io.ObjectInputStream", $buf);
* $this->java = $in->readObject();
* $in->close();
* }
* function getJava() {
* return $this->java;
* }
* function __destruct() {
* if($this->java) return $this->java->__destruct();
* }
* }
*
* class JPersistenceAdapter extends JPersistenceProxy {
* function __get($arg) { if($this->java) return $this->java->__get($arg); }
* function __put($key, $val) { if($this->java) return $this->java->__put($key, $val); }
* function __call($m, $a) { if($this->java) return $this->java->__call($m,$a); }
* function __toString() { if($this->java) return $this->java->__toString(); }
* }
* \endcode
*/
EXT_METHOD(EXT, __call)
{
zval **xargv, **argv;
int i = 0, xargc, argc = ZEND_NUM_ARGS();
HashPosition pos;
zval **param;
argv = (zval **) safe_emalloc(sizeof(zval *), argc, 0);
if (zend_get_parameters_array(ht, argc, argv) == FAILURE) {
php_error(E_ERROR, "Couldn't fetch arguments into array.");
RETURN_NULL();
}
/* function arguments in arg#2 */
xargc = zend_hash_num_elements(Z_ARRVAL_P(argv[1]));
xargv = safe_emalloc(sizeof(zval *), xargc, 0);
for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(argv[1]), &pos);
zend_hash_get_current_data_ex(Z_ARRVAL_P(argv[1]), (void **) ¶m, &pos) == SUCCESS;
zend_hash_move_forward_ex(Z_ARRVAL_P(argv[1]), &pos)) {
/*zval_add_ref(param);*/
xargv[i++] = *param;
}
EXT_GLOBAL(call_function_handler)(INTERNAL_FUNCTION_PARAM_PASSTHRU,
Z_STRVAL(*argv[0]), CONSTRUCTOR_NONE, 0,
getThis(),
xargc, xargv);
efree(argv);
efree(xargv);
}
/** Proto: object Java::__toString (void)
*
* Displays the java object as a string. Note: it doesn't cast the
* object to a string, thus echo "$ob" displays a string
* representation of $ob, e.g.: \code [o(String)"hello"]\endcode
*
* Use a string cast if you want to display the java string as a php
* string, e.g.:
* \code
* echo (string)$string;
* // implicit cast to string:
* echo "".$string;
* \endcode
*/
EXT_METHOD(EXT, __tostring)
{
long result = 0;
if(Z_TYPE_P(getThis()) == IS_OBJECT) {
EXT_GLOBAL(get_jobject_from_object)(getThis(), &result TSRMLS_CC);
}
if(result) {
proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C);
if(!jenv) {RETURN_NULL();}
(*jenv)->writeInvokeBegin(jenv, 0, "ObjectToString", 0, 'I', return_value);
(*jenv)->writeObject(jenv, result);
(*jenv)->writeInvokeEnd(jenv);
} else {
EXT_GLOBAL(call_function_handler)(INTERNAL_FUNCTION_PARAM_PASSTHRU,
"tostring", CONSTRUCTOR_NONE, 0, getThis(), 0, NULL);
}
}
/**
* Proto: void Java::__set(object, object)
*
* The setter
*
* Example: \code $obj->property = "value"; \endcode If no property
* exists, the bean properties are examined and a setter is called:
* \code $object->setProperty(value)\endcode
*/
EXT_METHOD(EXT, __set)
{
zval **argv;
int argc = ZEND_NUM_ARGS();
argv = (zval **) safe_emalloc(sizeof(zval *), argc, 0);
if (zend_get_parameters_array(ht, argc, argv) == FAILURE) {
php_error(E_ERROR, "Couldn't fetch arguments into array.");
RETURN_NULL();
}
EXT_GLOBAL(set_property_handler)(Z_STRVAL(*argv[0]), getThis(), argv[1], return_value);
efree(argv);
}
/**
* Proto: void Java::__destruct()
*
* Example:
* \code
*
* # The JSessionAdapter makes it possible to store java values into the
* # $_SESSION variable.
*
* # Example:
* # $vector = new JSessionAdapter(new Java("java.util.Vector"));
* # $vector->addElement(...);
* # $_SESSION["v"]=$vector;
*
*
* class JSessionProxy {
* var $java;
* var $serialID;
*
* function __construct($java){
* $this->java=$java;
* $this->serialID = uniqid("");
* }
* function __sleep() {
* $session=java_get_session("PHPSESSION".session_id());
* $session->put($this->serialID, $this->java);
* return array("serialID");
* }
* function __wakeup() {
* $session=java_get_session("PHPSESSION".session_id());
* $this->java = $session->get($this->serialID);
* }
* function getJava() {
* return $this->java;
* }
* function __destruct() {
* if($this->java) return $this->java->__destruct();
* }
* }
*
* class JSessionAdapter extends JSessionProxy {
* function __get($arg) { if($this->java) return $this->java->__get($arg); }
* function __put($key, $val) { if($this->java) return $this->java->__put($key, $val); }
* function __call($m, $a) { if($this->java) return $this->java->__call($m,$a); }
* function __toString() { if($this->java) return $this->java->__toString(); }
* }
* \endcode
*/
EXT_METHOD(EXT, __destruct)
{
/* dummy, see destroy_object in java_bridge.c */
}
/**
* Proto: object Java::__get(object)
*
* The getter. Example: \code echo (string) $object->property;
* \endcode If no property exists, the bean properties are examined
* and the getter is called, example: \code $object->getProperty()
* \endcode.
*/
EXT_METHOD(EXT, __get)
{
zval **argv;
int argc = ZEND_NUM_ARGS();
argv = (zval **) safe_emalloc(sizeof(zval *), argc, 0);
if (zend_get_parameters_array(ht, argc, argv) == FAILURE) {
php_error(E_ERROR, "Couldn't fetch arguments into array.");
RETURN_NULL();
}
EXT_GLOBAL(get_property_handler)(Z_STRVAL(*argv[0]), getThis(), return_value);
efree(argv);
}
/**
* Proto: string Java::__sleep()
*
* Serializes the object.
* Example:
* \code
* $vector=new JPersistenceAdapter(new Java("java.lang.StringBuffer", "hello"));
* $v=array (
* "test",
* $vector,
* 3.14);
* $id=serialize($v);
* $file=fopen("test.ser","w");
* fwrite($file, $id);
* fclose($file);
* \endcode
*/
EXT_METHOD(EXT, __sleep)
{
serialize(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/** Proto: string Java::__wakeup()
*
* Deserializes the object.
* Example:
* \code
* try {
* $v=unserialize($id);
* } catch (JavaException $e) {
* echo "Warning: Could not deserialize: ". $e->getCause() . "\n";
* }
* \endcode
*/
EXT_METHOD(EXT, __wakeup)
{
deserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/** Proto: bool Java::offsetExists()
*
* Checks if an object exists at the given position.
* Example:
* \code
* $System = new Java("java.lang.System");
* $props = $System->getProperties();
* if(!$props["user.home"]) die("No home dir!?!");
* \endcode
*/
EXT_METHOD(EXT, offsetExists)
{
proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C);
zval **argv;
int argc;
if(!jenv) {RETURN_NULL();}
argc = ZEND_NUM_ARGS();
argv = (zval **) safe_emalloc(sizeof(zval *), argc+1, 0);
if (zend_get_parameters_array(ht, argc, argv+1) == FAILURE) {
php_error(E_ERROR, "Couldn't fetch arguments into array.");
RETURN_NULL();
}
argv[0]=getThis();
EXT_GLOBAL(invoke)("offsetExists", 0, argc+1, argv, 0, return_value TSRMLS_CC);
efree(argv);
}
/**
* Proto: object Java::offsetGet()
*
* Get the object at a given position.
*
* Example:
* \code
* $System = new Java("java.lang.System");
* $props = $System->getProperties();
* echo $props["user.home"]);
* \endcode
*
*/
EXT_METHOD(EXT, offsetGet)
{
zval **argv;
int argc;
proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C);
if(!jenv) {RETURN_NULL();}
argc = ZEND_NUM_ARGS();
argv = (zval **) safe_emalloc(sizeof(zval *), argc+1, 0);
if (zend_get_parameters_array(ht, argc, argv+1) == FAILURE) {
php_error(E_ERROR, "Couldn't fetch arguments into array.");
RETURN_NULL();
}
argv[0]=getThis();
EXT_GLOBAL(invoke)("offsetGet", 0, argc+1, argv, 0, return_value TSRMLS_CC);
efree(argv);
}
/** Proto: void Java::offsetSet(object, object);
*
* Set the object at a given position. Example:
* \code
* $Array = new JavaClass("java.lang.reflect.Array");
* $testobj=$Array->newInstance(new JavaClass("java.lang.String"), array(2, 2, 2, 2, 2, 2));
*
* $testobj[0][0][0][0][0][1] = 1;
* $testobj[0][0][0][0][1][0] = 2;
* $testobj[0][0][0][1][0][0] = 3;
* $testobj[0][0][1][0][0][0] = 4;
* $testobj[0][1][0][0][0][0] = 5;
* $testobj[1][0][0][0][0][0] = 6;
* \endcode
*/
EXT_METHOD(EXT, offsetSet)
{
zval **argv;
int argc;
proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C);
if(!jenv) {RETURN_NULL();}
argc = ZEND_NUM_ARGS();
argv = (zval **) safe_emalloc(sizeof(zval *), argc+1, 0);
if (zend_get_parameters_array(ht, argc, argv+1) == FAILURE) {
php_error(E_ERROR, "Couldn't fetch arguments into array.");
RETURN_NULL();
}
argv[0]=getThis();
EXT_GLOBAL(invoke)("offsetSet", 0, argc+1, argv, 0, return_value TSRMLS_CC);
efree(argv);
}
/** Proto: string Java::offsetUnset()
*
* Remove the entry at a given position. Used internally.
*/
EXT_METHOD(EXT, offsetUnset)
{
zval **argv;
int argc;
long obj;
proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C);
if(!jenv) {RETURN_NULL();}
argc = ZEND_NUM_ARGS();
argv = (zval **) safe_emalloc(sizeof(zval *), argc+1, 0);
if (zend_get_parameters_array(ht, argc, argv+1) == FAILURE) {
php_error(E_ERROR, "Couldn't fetch arguments into array.");
RETURN_NULL();
}
argv[0]=getThis();
EXT_GLOBAL(invoke)("offsetUnset", 0, argc+1, argv, 0, return_value TSRMLS_CC);
efree(argv);
}
static
ZEND_BEGIN_ARG_INFO(arginfo_zero, 0)
ZEND_END_ARG_INFO();
static
ZEND_BEGIN_ARG_INFO(arginfo_get, 0)
ZEND_ARG_INFO(0, index)
ZEND_END_ARG_INFO();
static
ZEND_BEGIN_ARG_INFO(arginfo_set, 0)
ZEND_ARG_INFO(0, index)
ZEND_ARG_INFO(0, newval)
ZEND_END_ARG_INFO();
#ifndef ZEND_ENGINE_2
function_entry EXT_GLOBAL(class_functions)[] = {
EXT_ME(EXT, EXT, NULL, 0)
EXT_ME(EXT, EXT_GLOBAL(class), NULL, 0)
EXT_MALIAS(EXT, EXT_GLOBAL_N(class), EXT_GLOBAL(class), NULL, 0)
//EXT_MALIAS(EXT, __construct, EXT, arginfo_set, ZEND_ACC_PUBLIC)
EXT_ME(EXT, __call, arginfo_set, ZEND_ACC_PUBLIC)
EXT_ME(EXT, __tostring, arginfo_zero, ZEND_ACC_PUBLIC)
EXT_ME(EXT, __get, arginfo_get, ZEND_ACC_PUBLIC)
EXT_ME(EXT, __set, arginfo_set, ZEND_ACC_PUBLIC)
EXT_ME(EXT, __sleep, arginfo_zero, ZEND_ACC_PUBLIC)
EXT_ME(EXT, __wakeup, arginfo_zero, ZEND_ACC_PUBLIC)
EXT_ME(EXT, __destruct, arginfo_zero, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
#else
function_entry EXT_GLOBAL(class_functions)[] = {
ZEND_FENTRY(__construct, EXT_FN(EXT_GLOBAL(construct)), NULL, 0)
EXT_ME(EXT, __call, arginfo_set, ZEND_ACC_PUBLIC)
EXT_ME(EXT, __tostring, arginfo_zero, ZEND_ACC_PUBLIC)
EXT_ME(EXT, __get, arginfo_get, ZEND_ACC_PUBLIC)
EXT_ME(EXT, __set, arginfo_set, ZEND_ACC_PUBLIC)
EXT_ME(EXT, __sleep, arginfo_zero, ZEND_ACC_PUBLIC)
EXT_ME(EXT, __wakeup, arginfo_zero, ZEND_ACC_PUBLIC)
EXT_ME(EXT, __destruct, arginfo_zero, ZEND_ACC_PUBLIC)
//PHP_ME(EXT, __getFunctions, NULL, 0)
//PHP_ME(EXT, __getTypes, NULL, 0)
{NULL, NULL, NULL}
};
function_entry EXT_GLOBAL(array_class_functions)[] = {
ZEND_FENTRY(__construct, EXT_FN(EXT_GLOBAL(construct)), NULL, 0)
EXT_ME(EXT, offsetExists, arginfo_get, ZEND_ACC_PUBLIC)
EXT_ME(EXT, offsetGet, arginfo_get, ZEND_ACC_PUBLIC)
EXT_ME(EXT, offsetSet, arginfo_set, ZEND_ACC_PUBLIC)
EXT_ME(EXT, offsetUnset, arginfo_get, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
#endif
static int cast(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC)
{
proxyenv *jenv = EXT_GLOBAL(connect_to_server)(TSRMLS_C);
long obj = 0;
zval free_obj;
if(!jenv) return FAILURE;
if (should_free)
free_obj = *writeobj;
if(jenv && (Z_TYPE_P(readobj) == IS_OBJECT)) {
EXT_GLOBAL(get_jobject_from_object)(readobj, &obj TSRMLS_CC);
}
if(obj) {
ZVAL_NULL(writeobj);
switch(type) {
case IS_STRING:
(*jenv)->writeInvokeBegin(jenv, 0, "castToString", 0, 'I', writeobj);
(*jenv)->writeObject(jenv, obj);
(*jenv)->writeInvokeEnd(jenv);
break;
case IS_BOOL:
(*jenv)->writeInvokeBegin(jenv, 0, "castToBoolean", 0, 'I', writeobj);
(*jenv)->writeObject(jenv, obj);
(*jenv)->writeInvokeEnd(jenv);
break;
case IS_LONG:
(*jenv)->writeInvokeBegin(jenv, 0, "castToExact", 0, 'I', writeobj);
(*jenv)->writeObject(jenv, obj);
(*jenv)->writeInvokeEnd(jenv);
break;
case IS_DOUBLE:
(*jenv)->writeInvokeBegin(jenv, 0, "castToInexact", 0, 'I', writeobj);
(*jenv)->writeObject(jenv, obj);
(*jenv)->writeInvokeEnd(jenv);
break;
case IS_OBJECT:
{
long obj2;
if(jenv && (Z_TYPE_P(readobj) == IS_OBJECT)) {
EXT_GLOBAL(get_jobject_from_object)(readobj, &obj2 TSRMLS_CC);
}
if(obj2) {
(*jenv)->writeInvokeBegin(jenv, 0, "cast", 0, 'I', writeobj);
(*jenv)->writeObject(jenv, obj);
(*jenv)->writeObject(jenv, obj2);
(*jenv)->writeInvokeEnd(jenv);
} else {
obj = 0; //failed
}
}
break;
case IS_ARRAY:
#ifdef ZEND_ENGINE_2
(*jenv)->writeInvokeBegin(jenv, 0, "getValues", 0, 'I', writeobj);
(*jenv)->writeObject(jenv, obj);
(*jenv)->writeInvokeEnd(jenv);
#else
obj = 0; // failed
#endif
break;
}
}
if (should_free)
zval_dtor(&free_obj);
return obj?SUCCESS:FAILURE;
}
typedef struct {
zend_object_iterator intern;
long vm_iterator;
zval *current_object;
int type;
} vm_iterator;
static void iterator_dtor(zend_object_iterator *iter TSRMLS_DC)
{
proxyenv *jenv = JG(jenv);
vm_iterator *iterator = (vm_iterator *)iter;
zval_ptr_dtor((zval**)&iterator->intern.data);
if (iterator->current_object) zval_ptr_dtor((zval**)&iterator->current_object);
if(iterator->vm_iterator) {
/* check jenv because destructor may be called after request
shutdown */
if(jenv) (*jenv)->writeUnref(jenv, iterator->vm_iterator);
iterator->vm_iterator = 0;
}
efree(iterator);
}
static int iterator_valid(zend_object_iterator *iter TSRMLS_DC)
{
vm_iterator *iterator = (vm_iterator *)iter;
return (iterator->vm_iterator && iterator->current_object) ? SUCCESS : FAILURE;
}
static void iterator_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
{
vm_iterator *iterator = (vm_iterator *)iter;
*data = &iterator->current_object;
}
static int iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
{
vm_iterator *iterator = (vm_iterator *)iter;
zval *presult;
MAKE_STD_ZVAL(presult);
ZVAL_NULL(presult);
EXT_GLOBAL(invoke)("currentKey", iterator->vm_iterator, 0, 0, 0, presult TSRMLS_CC);
if(ZVAL_IS_NULL(presult)) {
zval_ptr_dtor((zval**)&presult);
return HASH_KEY_NON_EXISTANT;
}
if(iterator->type == HASH_KEY_IS_STRING) {
size_t strlen = Z_STRLEN_P(presult);
*str_key = emalloc(strlen+1);
memcpy(*str_key, Z_STRVAL_P(presult), strlen);
(*str_key)[strlen]=0;
// len+1 is due to a bug in php. It assignes the len with
// key->value.str.len = str_key_len-1; In the evaluator the
// obtained length is always increased by one, except for the
// return value from iterator_current_key. So we must do this
// ourselfs. The author's intention was probably to discard the
// termination character, but that's pointless, if php expects our
// string to be null terminated why does it ask for the string
// length? And if it doesn't expect a null terminated string, why
// does it decrease the obtained length by one?
*str_key_len = strlen+1;
} else {
ulong i =(unsigned long)atol((char*)Z_STRVAL_P(presult));
*int_key = i;
}
zval_ptr_dtor((zval**)&presult);
return iterator->type;
}
static void init_current_data(vm_iterator *iterator TSRMLS_DC)
{
MAKE_STD_ZVAL(iterator->current_object);
ZVAL_NULL(iterator->current_object);
EXT_GLOBAL(invoke)("currentData", iterator->vm_iterator, 0, 0, 0, iterator->current_object TSRMLS_CC);
}
static void iterator_move_forward(zend_object_iterator *iter TSRMLS_DC)
{
zval *presult;
vm_iterator *iterator = (vm_iterator *)iter;
proxyenv *jenv = JG(jenv);
MAKE_STD_ZVAL(presult);
ZVAL_NULL(presult);
if (iterator->current_object) {
zval_ptr_dtor((zval**)&iterator->current_object);
iterator->current_object = NULL;
}
(*jenv)->writeInvokeBegin(jenv, iterator->vm_iterator, "moveForward", 0, 'I', presult);
(*jenv)->writeInvokeEnd(jenv);
if(Z_BVAL_P(presult))
init_current_data(iterator TSRMLS_CC);
zval_ptr_dtor((zval**)&presult);
}
static zend_object_iterator_funcs EXT_GLOBAL(iterator_funcs) = {
iterator_dtor,
iterator_valid,
iterator_current_data,
iterator_current_key,
iterator_move_forward,
NULL
};
static zend_object_iterator *get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC)
{
zval *presult;
proxyenv *jenv = JG(jenv);
vm_iterator *iterator = emalloc(sizeof *iterator);
long vm_iterator, obj;
MAKE_STD_ZVAL(presult);
ZVAL_NULL(presult);
object->refcount++;
iterator->intern.data = (void*)object;
iterator->intern.funcs = &EXT_GLOBAL(iterator_funcs);
EXT_GLOBAL(get_jobject_from_object)(object, &obj TSRMLS_CC);
assert(obj);
(*jenv)->writeInvokeBegin(jenv, 0, "getPhpMap", 0, 'I', presult);
(*jenv)->writeObject(jenv, obj);
(*jenv)->writeInvokeEnd(jenv);
EXT_GLOBAL(get_jobject_from_object)(presult, &vm_iterator TSRMLS_CC);
if (!vm_iterator) return NULL;
iterator->vm_iterator = vm_iterator;
(*jenv)->writeInvokeBegin(jenv, vm_iterator, "getType", 0, 'I', presult);
(*jenv)->writeInvokeEnd(jenv);
iterator->type = Z_BVAL_P(presult) ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG;
(*jenv)->writeInvokeBegin(jenv, vm_iterator, "hasMore", 0, 'I', presult);
(*jenv)->writeInvokeEnd(jenv);
if(Z_BVAL_P(presult))
init_current_data(iterator TSRMLS_CC);
else
iterator->current_object = NULL;
zval_ptr_dtor((zval**)&presult);
return (zend_object_iterator*)iterator;
}
static void make_lambda(zend_internal_function *f,
void (*handler)(INTERNAL_FUNCTION_PARAMETERS))
{
f->type = ZEND_INTERNAL_FUNCTION;
f->handler = handler;
f->function_name = NULL;
f->scope = NULL;
f->fn_flags = 0;
f->prototype = NULL;
f->num_args = 0;
f->arg_info = NULL;
f->pass_rest_by_reference = 0;
}
#else
static int make_lambda(zend_internal_function *f,
void (*handler)(INTERNAL_FUNCTION_PARAMETERS))
{
f->type = ZEND_INTERNAL_FUNCTION;
f->handler = handler;
f->function_name = NULL;
f->arg_types = NULL;
}
/**
* Call function handler for php4
*/
void
EXT_GLOBAL(call_function_handler4)(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference)
{
pval *object = property_reference->object;
zend_overloaded_element *function_name = (zend_overloaded_element *)
property_reference->elements_list->tail->data;
char *name = Z_STRVAL(function_name->element);
int arg_count = ZEND_NUM_ARGS();
pval **arguments = (pval **) emalloc(sizeof(pval *)*arg_count);
enum constructor constructor = CONSTRUCTOR_NONE;
zend_class_entry *ce = Z_OBJCE_P(getThis());
/* Do not create an instance for new
java_class or new JavaClass */
short createInstance=!instanceof_function(ce, EXT_GLOBAL(class_class_entry) TSRMLS_CC);
getParametersArray(ht, arg_count, arguments);
if(!strcmp(name, ce->name)) constructor = CONSTRUCTOR;
EXT_GLOBAL(call_function_handler)(INTERNAL_FUNCTION_PARAM_PASSTHRU,
name, constructor, createInstance,
object,
arg_count, arguments);
efree(arguments);
pval_destructor(&function_name->element);
}
static pval
get_property_handler(zend_property_reference *property_reference)
{
pval presult, *object;
zend_llist_element *element;
zend_overloaded_element *property;
char *name;
element = property_reference->elements_list->head;
property=(zend_overloaded_element *)element->data;
name = Z_STRVAL(property->element);
object = property_reference->object;
EXT_GLOBAL(get_property_handler)(name, object, &presult);
pval_destructor(&property->element);
return presult;
}
static int
set_property_handler(zend_property_reference *property_reference, pval *value)
{
int result;
pval dummy, *object;
zend_llist_element *element;
zend_overloaded_element *property;
char *name;
element = property_reference->elements_list->head;
property=(zend_overloaded_element *)element->data;
name = Z_STRVAL(property->element);
object = property_reference->object;
result = EXT_GLOBAL(set_property_handler) (name, object, value, &dummy);
pval_destructor(&property->element);
return result;
}
#endif
static void make_local_socket_info(TSRMLS_D) {
memset(&EXT_GLOBAL(cfg)->saddr, 0, sizeof EXT_GLOBAL(cfg)->saddr);
#ifndef CFG_JAVA_SOCKET_INET
EXT_GLOBAL(cfg)->saddr.sun_family = AF_LOCAL;
memset(EXT_GLOBAL(cfg)->saddr.sun_path, 0, sizeof EXT_GLOBAL(cfg)->saddr.sun_path);
strcpy(EXT_GLOBAL(cfg)->saddr.sun_path, EXT_GLOBAL(get_sockname)(TSRMLS_C));
# ifdef HAVE_ABSTRACT_NAMESPACE
*EXT_GLOBAL(cfg)->saddr.sun_path=0;
# endif
#else
EXT_GLOBAL(cfg)->saddr.sin_family = AF_INET;
EXT_GLOBAL(cfg)->saddr.sin_port=htons(atoi(EXT_GLOBAL(get_sockname)(TSRMLS_C)));
EXT_GLOBAL(cfg)->saddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
#endif
}
/**
* Called when the module is initialized. Creates the Java and
* JavaClass structures and tries to start the backend if
* java.socketname, java.servlet or java.hosts are not set. The
* backend 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
* CGI binary, it is called whenever the CGI binary is called.
*/
PHP_MINIT_FUNCTION(EXT)
{
zend_class_entry *parent;
#ifndef ZEND_ENGINE_2
static const char nserialize[]="__sleep", ndeserialize[]="__wakeup";
zend_internal_function serialize, deserialize;
zend_class_entry ce;
INIT_OVERLOADED_CLASS_ENTRY(ce, EXT_NAME(), NULL,
EXT_GLOBAL(call_function_handler4),
get_property_handler,
set_property_handler);
EXT_GLOBAL(class_entry) = zend_register_internal_class(&ce TSRMLS_CC);
INIT_CLASS_ENTRY(ce, EXT_NAME()/**/"_class", NULL);
parent = (zend_class_entry *) EXT_GLOBAL(class_entry);
EXT_GLOBAL(class_class_entry) =
zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC);
INIT_CLASS_ENTRY(ce, EXT_NAME()/**/"class", NULL);
parent = (zend_class_entry *) EXT_GLOBAL(class_class_entry);
EXT_GLOBAL(class_class_entry_jsr) =
zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC);
make_lambda(&serialize, EXT_FN(EXT_GLOBAL(__sleep)));
make_lambda(&deserialize, EXT_FN(EXT_GLOBAL(__wakeup)));
if((FAILURE == (zend_hash_add(&EXT_GLOBAL(class_entry)->function_table,
(char*)nserialize, sizeof(nserialize), &serialize, sizeof(zend_function), NULL))) ||
(FAILURE == (zend_hash_add(&EXT_GLOBAL(class_entry)->function_table,
(char*)ndeserialize, sizeof(ndeserialize), &deserialize, sizeof(zend_function), NULL))))
{
php_error(E_ERROR, "Could not register __sleep/__wakeup methods.");
return FAILURE;
}
#else
zend_class_entry ce;
zend_internal_function call, get, set;
make_lambda(&call, EXT_FN(EXT_GLOBAL(__call)));
make_lambda(&get, EXT_FN(EXT_GLOBAL(__get)));
make_lambda(&set, EXT_FN(EXT_GLOBAL(__set)));
INIT_OVERLOADED_CLASS_ENTRY(ce, EXT_NAME(),
EXT_GLOBAL(class_functions),
(zend_function*)&call,
(zend_function*)&get,
(zend_function*)&set);
memcpy(&EXT_GLOBAL(handlers), zend_get_std_object_handlers(), sizeof EXT_GLOBAL(handlers));
//EXT_GLOBAL(handlers).clone_obj = clone;
EXT_GLOBAL(handlers).cast_object = cast;
EXT_GLOBAL(class_entry) =
zend_register_internal_class(&ce TSRMLS_CC);
EXT_GLOBAL(class_entry)->get_iterator = get_iterator;
EXT_GLOBAL(class_entry)->create_object = EXT_GLOBAL(create_object);
INIT_CLASS_ENTRY(ce, EXT_NAME()/**/"Array",
EXT_GLOBAL(array_class_functions));
parent = (zend_class_entry *) EXT_GLOBAL(class_entry);
EXT_GLOBAL(array_entry) =
zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC);
zend_class_implements(EXT_GLOBAL(array_entry) TSRMLS_CC, 1,
zend_ce_arrayaccess);
INIT_OVERLOADED_CLASS_ENTRY(ce, EXT_NAME()/**/"_exception",
EXT_GLOBAL(class_functions),
(zend_function*)&call,
(zend_function*)&get,
(zend_function*)&set);
parent = (zend_class_entry *) zend_exception_get_default();
EXT_GLOBAL(exception_class_entry) =
zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC);
// only cast and clone; no iterator, no array access
EXT_GLOBAL(exception_class_entry)->create_object = EXT_GLOBAL(create_exception_object);
INIT_CLASS_ENTRY(ce, EXT_NAME()/**/"_class", EXT_GLOBAL(class_functions));
parent = (zend_class_entry *) EXT_GLOBAL(class_entry);
EXT_GLOBAL(class_class_entry) =
zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC);
/* compatibility with the jsr implementation */
INIT_CLASS_ENTRY(ce, EXT_NAME()/**/"class", EXT_GLOBAL(class_functions));
parent = (zend_class_entry *) EXT_GLOBAL(class_entry);
EXT_GLOBAL(class_class_entry_jsr) =
zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC);
INIT_CLASS_ENTRY(ce, EXT_NAME()/**/"exception", EXT_GLOBAL(class_functions));
parent = (zend_class_entry *) EXT_GLOBAL(exception_class_entry);
EXT_GLOBAL(exception_class_entry) =
zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC);
#endif
EXT_INIT_MODULE_GLOBALS(EXT, EXT_GLOBAL(alloc_globals_ctor), NULL);
assert(!EXT_GLOBAL (cfg) );
if(!EXT_GLOBAL (cfg) ) EXT_GLOBAL (cfg) = malloc(sizeof *EXT_GLOBAL (cfg) ); if(!EXT_GLOBAL (cfg) ) exit(9);
if(REGISTER_INI_ENTRIES()==SUCCESS) {
/* set the default values for all undefined */
EXT_GLOBAL(init_cfg) (TSRMLS_C);
make_local_socket_info(TSRMLS_C);
clone_cfg(TSRMLS_C);
EXT_GLOBAL(start_server) (TSRMLS_C);
destroy_cloned_cfg(TSRMLS_C);
}
return SUCCESS;
}
/**
* Displays the module info.
*/
PHP_MINFO_FUNCTION(EXT)
{
short is_local;
char*s=EXT_GLOBAL(get_server_string) (TSRMLS_C);
char*server = EXT_GLOBAL(test_server) (0, &is_local, 0 TSRMLS_CC);
short is_level = ((EXT_GLOBAL (ini_user)&U_LOGLEVEL)!=0);
php_info_print_table_start();
php_info_print_table_row(2, EXT_NAME()/**/" support", "Enabled");
php_info_print_table_row(2, EXT_NAME()/**/" bridge", EXT_GLOBAL(bridge_version));
#if EXTENSION == JAVA
if(is_local) {
/* don't show default value, they may
not be used anyway */
if((EXT_GLOBAL(option_set_by_user) (U_LIBRARY_PATH, EXT_GLOBAL(ini_user))))
php_info_print_table_row(2, EXT_NAME()/**/".libpath", EXT_GLOBAL(cfg)->ld_library_path);
/* don't show default value, they may
not be used anyway */
if((EXT_GLOBAL(option_set_by_user) (U_CLASSPATH, EXT_GLOBAL(ini_user))))
php_info_print_table_row(2, EXT_NAME()/**/".classpath", EXT_GLOBAL(cfg)->classpath);
}
#endif
if(!server || is_local) {
static const char default_wrapper[] = "no value (use default wrapper)";
php_info_print_table_row(2, EXT_NAME()/**/"."/**/EXT_NAME()/**/"_home", EXT_GLOBAL(cfg)->vm_home);
php_info_print_table_row(2, EXT_NAME()/**/"."/**/EXT_NAME(), EXT_GLOBAL(cfg)->vm);
php_info_print_table_row(2, EXT_NAME()/**/".wrapper", (EXT_GLOBAL(option_set_by_user) (U_WRAPPER, EXT_GLOBAL(ini_user))) ? EXT_GLOBAL(cfg)->wrapper : (char*)default_wrapper);
if(strlen(EXT_GLOBAL(cfg)->logFile)==0)
php_info_print_table_row(2, EXT_NAME()/**/".log_file", "<stdout>");
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()/**/".hosts", JG(hosts));
#if EXTENSION == JAVA
php_info_print_table_row(2, EXT_NAME()/**/".servlet", JG(servlet)?JG(servlet):off);
#endif
if(!server || is_local) {
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");
php_info_print_table_end();
free(server);
free(s);
}
/**
* Called when the module terminates. Stops the backend, 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(destroy_cfg) (EXT_GLOBAL(ini_set));
EXT_GLOBAL(ini_user) = EXT_GLOBAL(ini_set) = 0;
UNREGISTER_INI_ENTRIES();
EXT_GLOBAL(shutdown_library) ();
assert(EXT_GLOBAL (cfg));
if(EXT_GLOBAL (cfg) ) { free(EXT_GLOBAL (cfg) ); EXT_GLOBAL (cfg) = 0; }
return SUCCESS;
}
#ifndef PHP_WRAPPER_H
#error must include php_wrapper.h
#endif