From 1c4fad926ce79d3a84155354aa3e42524a9ab228 Mon Sep 17 00:00:00 2001 From: sebastien Date: Sun, 23 Apr 2017 20:10:46 +0200 Subject: [PATCH 1/8] Merge changes from upstream 7.1.3 (wip) --- CHANGELOG.md | 2 + doc/upstream/upstream_merge_notes.md | 63 + legacy/server/META-INF/java/Client.inc | 1183 ++++++------ legacy/server/META-INF/java/JavaProxy.inc | 1276 ++++++------- legacy/server/META-INF/java/Protocol.inc | 1640 +++++++++-------- .../io/soluble/pjb/bridge/DefaultOptions.java | 2 +- .../java/io/soluble/pjb/bridge/GlobalRef.java | 2 +- .../io/soluble/pjb/bridge/JavaBridge.java | 56 +- .../java/io/soluble/pjb/bridge/JavaInc.java | 8 + .../io/soluble/pjb/bridge/MethodCache.java | 2 +- .../io/soluble/pjb/bridge/ParserString.java | 2 +- .../java/io/soluble/pjb/bridge/PhpArray.java | 2 +- .../io/soluble/pjb/bridge/PhpExactNumber.java | 2 +- .../io/soluble/pjb/bridge/PhpProcedure.java | 4 +- .../java/io/soluble/pjb/bridge/PhpString.java | 2 +- .../java/io/soluble/pjb/bridge/Request.java | 7 +- .../java/io/soluble/pjb/bridge/Session.java | 18 +- .../io/soluble/pjb/bridge/SessionFactory.java | 10 +- .../soluble/pjb/bridge/SimplePhpString.java | 2 +- .../io/soluble/pjb/bridge/StringCache.java | 2 +- .../io/soluble/pjb/bridge/http/Context.java | 12 + .../io/soluble/pjb/bridge/http/IContext.java | 4 + .../pjb/script/AbstractPhpScriptContext.java | 15 + .../pjb/script/PhpScriptContextDecorator.java | 13 + src/main/resources/META-INF/java/Java.inc | 8 + src/main/webapp/java/Java.inc | 8 + 26 files changed, 2262 insertions(+), 2083 deletions(-) create mode 100644 doc/upstream/upstream_merge_notes.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a788bc..009e01d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ when stabilized. ### Added +- `Client->setExitCode()`, `Protocol->setExitCode()` from upstream. + ### Changed diff --git a/doc/upstream/upstream_merge_notes.md b/doc/upstream/upstream_merge_notes.md new file mode 100644 index 0000000..fabd301 --- /dev/null +++ b/doc/upstream/upstream_merge_notes.md @@ -0,0 +1,63 @@ +# Upstream notes + +## CVS + +### Checkout release + +```shell +cvs -z3 -d:pserver:anonymous@php-java-bridge.cvs.sourceforge.net:/cvsroot/php-java-bridge co -P php-java-bridge +``` + +### Export specific branch + +```shell +cvs -z3 -d:pserver:anonymous@php-java-bridge.cvs.sourceforge.net:/cvsroot/php-java-bridge export -d pjb7.0.1 -r Release_7-0-1 php-java-bridge +``` + +or head + +```shell +cvs -z3 -d:pserver:anonymous@php-java-bridge.cvs.sourceforge.net:/cvsroot/php-java-bridge export -d pjb-head -r HEAD php-java-bridge +``` + +### List releases + +This command list all branches on the original sourceforge repo + +```shell +cvs -Q -d :pserver:anonymous@php-java-bridge.cvs.sourceforge.net:/cvsroot/php-java-bridge rlog -h php-java-bridge | awk -F"[.:]" '/^\t/&&$(NF-1)==0{print $1}' | sort -u +``` + +You can optionally list all tags: + +```shell +cvs -Q -d :pserver:anonymous@php-java-bridge.cvs.sourceforge.net:/cvsroot/php-java-bridge rlog -h php-java-bridge | awk -F"[.:]" '/^\t/&&$(NF-1)!=0{print $1}' | sort -u +``` + +> Prefer using branches instead of tags for the sourceforge release. Not every release was tagged. + +### Compare changes + +You can compare changes made on releases, first checkout head and run: + +For changed files: + + ```shell + cvs diff -N -c -r Release_7-0-1 -r HEAD > pjb701-head.diff + ``` + +For rdiff summary: + + ```shell + cvs rdiff -s -r Release_7-0-1 -r HEAD php-java-bridge > rdiff-701-head-summary.txt + ``` + +## Example + +### 7.0.1 to HEAD + +```shell +# Save head in directory ./pjb-head +cvs -z3 -d:pserver:anonymous@php-java-bridge.cvs.sourceforge.net:/cvsroot/php-java-bridge export -d pjb-head -r HEAD php-java-bridge + +``` \ No newline at end of file diff --git a/legacy/server/META-INF/java/Client.inc b/legacy/server/META-INF/java/Client.inc index ba3e9c9..3ce102e 100644 --- a/legacy/server/META-INF/java/Client.inc +++ b/legacy/server/META-INF/java/Client.inc @@ -1,47 +1,47 @@ client = $client; - } - function getProxy($result, $signature, $exception, $wrap) { - return $result; - } - function checkResult($result) { - } + public $client; + function __construct($client) { + $this->client = $client; + } + function getProxy($result, $signature, $exception, $wrap) { + return $result; + } + function checkResult($result) { + } } /** * @access private */ class java_ProxyFactory extends java_SimpleFactory { - function create($result, $signature) { - return new java_JavaProxy($result, $signature); - } - function createInternal($proxy) { - return new java_InternalJava($proxy); - } - function getProxy($result, $signature, $exception, $wrap) { - $proxy = $this->create($result, $signature); - if($wrap) $proxy = $this->createInternal($proxy); - return $proxy; - } + function create($result, $signature) { + return new java_JavaProxy($result, $signature); + } + function createInternal($proxy) { + return new java_InternalJava($proxy); + } + function getProxy($result, $signature, $exception, $wrap) { + $proxy = $this->create($result, $signature); + if($wrap) $proxy = $this->createInternal($proxy); + return $proxy; + } } /** * @access private */ class java_ArrayProxyFactory extends java_ProxyFactory { - function create($result, $signature) { - return new java_ArrayProxy($result, $signature); - } + function create($result, $signature) { + return new java_ArrayProxy($result, $signature); + } } /** * @access private */ class java_IteratorProxyFactory extends java_ProxyFactory { - function create($result, $signature) { - return new java_IteratorProxy($result, $signature); - } + function create($result, $signature) { + return new java_IteratorProxy($result, $signature); + } } /** * @access private */ class java_ExceptionProxyFactory extends java_SimpleFactory { - function create($result, $signature) { - return new java_ExceptionProxy($result, $signature); - } - function getProxy($result, $signature, $exception, $wrap) { - $proxy = $this->create($result, $signature); - if($wrap) $proxy = new java_InternalException($proxy, $exception); - return $proxy; - } + function create($result, $signature) { + return new java_ExceptionProxy($result, $signature); + } + function getProxy($result, $signature, $exception, $wrap) { + $proxy = $this->create($result, $signature); + if($wrap) $proxy = new java_InternalException($proxy, $exception); + return $proxy; + } } /** * @access private */ class java_ThrowExceptionProxyFactory extends java_ExceptionProxyFactory { - function getProxy($result, $signature, $exception, $wrap) { - $proxy = $this->create($result, $signature); - // don't check for $wrap, which may be wrong (type Java instead of - // JavaException) when the user has managed to create an exception - // from a Java constructor, e.g.: new Java("java.lang.String", - // null). Since we'll discard the possibly wrong type anyway, we - // can create a fresh proxy without any further checks: - - $proxy = new java_InternalException($proxy, $exception); - return $proxy; - } - function checkResult($result) { - if (JAVA_PREFER_VALUES || ($result->__hasDeclaredExceptions=='T')) - throw $result; - else { - trigger_error("Unchecked exception detected: ".java_truncate($result->__toString()), E_USER_WARNING); - } - } + function getProxy($result, $signature, $exception, $wrap) { + $proxy = $this->create($result, $signature); + // don't check for $wrap, which may be wrong (type Java instead of + // JavaException) when the user has managed to create an exception + // from a Java constructor, e.g.: new Java("java.lang.String", + // null). Since we'll discard the possibly wrong type anyway, we + // can create a fresh proxy without any further checks: + + $proxy = new java_InternalException($proxy, $exception); + return $proxy; + } + function checkResult($result) { + if (JAVA_PREFER_VALUES || ($result->__hasDeclaredExceptions=='T')) + throw $result; + else { + trigger_error("Unchecked exception detected: ".java_truncate($result->__toString()), E_USER_WARNING); + } + } } /** * @access private */ class java_CacheEntry { - public $fmt, $signature, $factory, $java; - public $resultVoid; - - function __construct($fmt, $signature, $factory, $resultVoid) { - $this->fmt = $fmt; - $this->signature = $signature; - $this->factory = $factory; - $this->resultVoid = $resultVoid; - } + public $fmt, $signature, $factory, $java; + public $resultVoid; + + function __construct($fmt, $signature, $factory, $resultVoid) { + $this->fmt = $fmt; + $this->signature = $signature; + $this->factory = $factory; + $this->resultVoid = $resultVoid; + } } /** * @access private */ class java_Arg { - public $client; - public $exception; // string representation for php4 - public $factory, $val; - public $signature; // class type - - function __construct($client) { - $this->client = $client; - $this->factory = $client->simpleFactory; - } - function linkResult(&$val) { - $this->val = &$val; - } - function setResult($val) { - $this->val = &$val; - } - function getResult($wrap) { - $rc = $this->factory->getProxy($this->val, $this->signature, $this->exception, $wrap); - $factory = $this->factory; - - $this->factory = $this->client->simpleFactory; - $factory->checkResult($rc); - return $rc; - } - function setFactory($factory) { - $this->factory = $factory; - } - function setException($string) { - $this->exception = $string; - } - function setVoidSignature() { - $this->signature = "@V"; - // update cache - $key = $this->client->currentCacheKey; - if($key && $key[0]!='~') { // do not cache array(...) or non-java objects - $this->client->currentArgumentsFormat[6]="3"; - if(JAVA_DEBUG) {echo "ignore further results:"; echo "\n";} - if(JAVA_DEBUG) {echo "updating cache $key, argformat: {$this->client->currentArgumentsFormat}, classType: {$this->signature}\n";} - $cacheEntry = new java_CacheEntry($this->client->currentArgumentsFormat, $this->signature, $this->factory, true); - $this->client->methodCache[$key]=$cacheEntry; - } - } - function setSignature($signature) { - $this->signature = $signature; - // update cache - $key = $this->client->currentCacheKey; - if($key && $key[0]!='~') { // do not cache array(...) or non-java objects - if(JAVA_DEBUG) {echo "updating cache $key, argformat: {$this->client->currentArgumentsFormat}, classType: {$this->signature}\n";} - $cacheEntry = new java_CacheEntry($this->client->currentArgumentsFormat, $this->signature, $this->factory, false); - $this->client->methodCache[$key]=$cacheEntry; - } - } + public $client; + public $exception; // string representation for php4 + public $factory, $val; + public $signature; // class type + + function __construct($client) { + $this->client = $client; + $this->factory = $client->simpleFactory; + } + function linkResult(&$val) { + $this->val = &$val; + } + function setResult($val) { + $this->val = &$val; + } + function getResult($wrap) { + $rc = $this->factory->getProxy($this->val, $this->signature, $this->exception, $wrap); + $factory = $this->factory; + + $this->factory = $this->client->simpleFactory; + $factory->checkResult($rc); + return $rc; + } + function setFactory($factory) { + $this->factory = $factory; + } + function setException($string) { + $this->exception = $string; + } + function setVoidSignature() { + $this->signature = "@V"; + // update cache + $key = $this->client->currentCacheKey; + if($key && $key[0]!='~') { // do not cache array(...) or non-java objects + $this->client->currentArgumentsFormat[6]="3"; + if(JAVA_DEBUG) {echo "ignore further results:"; echo "\n";} + if(JAVA_DEBUG) {echo "updating cache $key, argformat: {$this->client->currentArgumentsFormat}, classType: {$this->signature}\n";} + $cacheEntry = new java_CacheEntry($this->client->currentArgumentsFormat, $this->signature, $this->factory, true); + $this->client->methodCache[$key]=$cacheEntry; + } + } + function setSignature($signature) { + $this->signature = $signature; + // update cache + $key = $this->client->currentCacheKey; + if($key && $key[0]!='~') { // do not cache array(...) or non-java objects + if(JAVA_DEBUG) {echo "updating cache $key, argformat: {$this->client->currentArgumentsFormat}, classType: {$this->signature}\n";} + $cacheEntry = new java_CacheEntry($this->client->currentArgumentsFormat, $this->signature, $this->factory, false); + $this->client->methodCache[$key]=$cacheEntry; + } + } } /** * @access private */ class java_CompositeArg extends java_Arg { - public $parentArg; - public $idx; // position within $val; - public $type; // for A and X - public $counter; - - function __construct($client, $type) { - parent::__construct($client); - $this->type = $type; - $this->val = array(); - $this->counter = 0; - } - function setNextIndex() { - $this->idx = $this->counter++; - } - function setIndex($val) { - $this->idx = $val; - } - function linkResult(&$val) { - $this->val[$this->idx]=&$val; - } - function setResult($val) { - $this->val[$this->idx]=$this->factory->getProxy($val, $this->signature, $this->exception, true); - $this->factory = $this->client->simpleFactory; - } + public $parentArg; + public $idx; // position within $val; + public $type; // for A and X + public $counter; + + function __construct($client, $type) { + parent::__construct($client); + $this->type = $type; + $this->val = array(); + $this->counter = 0; + } + function setNextIndex() { + $this->idx = $this->counter++; + } + function setIndex($val) { + $this->idx = $val; + } + function linkResult(&$val) { + $this->val[$this->idx]=&$val; + } + function setResult($val) { + $this->val[$this->idx]=$this->factory->getProxy($val, $this->signature, $this->exception, true); + $this->factory = $this->client->simpleFactory; + } } /** * @access private */ class java_ApplyArg extends java_CompositeArg { - public $m, $p, $v, $n; // see PROTOCOL.TXT - - function __construct($client, $type, $m, $p, $v, $n) { - parent::__construct($client, $type); - $this->m = $m; - $this->p = $p; - $this->v = $v; - $this->n = $n; - } + public $m, $p, $v, $n; // see PROTOCOL.TXT + + function __construct($client, $type, $m, $p, $v, $n) { + parent::__construct($client, $type); + $this->m = $m; + $this->p = $p; + $this->v = $v; + $this->n = $n; + } } /** * @access private */ class java_Client /* implements IDocHandler */ { - public $RUNTIME; - - public $result, $exception; - public $parser; - - public $simpleArg, $compositeArg; - public $simpleFactory, - $proxyFactory, $iteratorProxyFacroty, - $arrayProxyFactory, $exceptionProxyFactory, $throwExceptionProxyFactory; - - public $arg; - public $asyncCtx, $cancelProxyCreationTag; - public $globalRef; - - public $stack; - - // the cache - public $defaultCache = array(), $asyncCache = array(), $methodCache; - public $isAsync = 0; - public $currentCacheKey, $currentArgumentsFormat; - public $cachedJavaPrototype; - - - // send buffer - public $sendBuffer, $preparedToSendBuffer; - - // do not finish protocol if ags construction fails due to PHP OutOfMemory error - public $inArgs; - - function __construct() { - $this->RUNTIME = array(); - $this->RUNTIME["NOTICE"]='***USE echo java_inspect(jVal) OR print_r(java_values(jVal)) TO SEE THE CONTENTS OF THIS JAVA OBJECT!***'; - - $this->parser = new java_Parser($this); - $this->protocol = new java_Protocol($this); - - $this->simpleFactory = new java_SimpleFactory($this); - $this->proxyFactory = new java_ProxyFactory($this); - $this->arrayProxyFactory = new java_ArrayProxyFactory($this); - $this->iteratorProxyFactory = new java_IteratorProxyFactory($this); - $this->exceptionProxyFactory = new java_ExceptionProxyFactory($this); - $this->throwExceptionProxyFactory = new java_ThrowExceptionProxyFactory($this); - - $this->cachedJavaPrototype=new java_JavaProxyProxy($this); - - $this->simpleArg = new java_Arg($this); - - $this->globalRef = new java_GlobalRef(); - - $this->asyncCtx = $this->cancelProxyCreationTag = 0; - - $this->methodCache = $this->defaultCache; - - $this->inArgs = false; - } - - function read($size) { - return $this->protocol->read($size); - } - - function setDefaultHandler() { - $this->methodCache = $this->defaultCache; - } - - function setAsyncHandler() { - $this->methodCache = $this->asyncCache; - } - - - function handleRequests() { - $tail_call = false; - do { - $this->stack=array($this->arg=$this->simpleArg); - $this->idx = 0; - $this->parser->parse(); - - /* pull off A, if any */ - if((count($this->stack)) > 1) { - $arg = array_pop($this->stack); - $this->apply($arg); - $tail_call = true; // we don't expect a result - } else { - $tail_call = false; - } - - $this->stack=null; - } while($tail_call); - return 1; - } - - function getWrappedResult($wrap) { - return $this->simpleArg->getResult($wrap); - } - function getInternalResult() { - return $this->getWrappedResult(false); - } - function getResult() { - return $this->getWrappedResult(true); - } - function getProxyFactory($type) { - switch($type[0]) { - case 'E': - $factory = $this->exceptionProxyFactory; - break; - case 'C': - $factory = $this->iteratorProxyFactory; - break; - case 'A': - $factory = $this->arrayProxyFactory; - break; - default: - case 'O': - $factory = $this->proxyFactory; - } - return $factory; - } - function link(&$arg, &$newArg) { - $arg->linkResult($newArg->val); - $newArg->parentArg = $arg; - } - function getExact($str) { - return hexdec($str); - } - function getInexact($str) { - $val = null; - sscanf($str, "%e", $val); - return $val; - } - function begin($name, $st) { - $arg = $this->arg; - switch($name[0]) { - case 'A': /* receive apply args as normal array */ - $object = $this->globalRef->get($this->getExact($st['v'])); - $newArg = new java_ApplyArg($this, 'A', - $this->parser->getData($st['m']), - $this->parser->getData($st['p']), - $object, - $this->getExact($st['n'])); - $this->link($arg, $newArg); - array_push($this->stack, $this->arg = $newArg); - break; - case 'X': - $newArg = new java_CompositeArg($this, $st['t']); - $this->link($arg, $newArg); - array_push($this->stack, $this->arg = $newArg); - break; - case 'P': - if($arg->type=='H') { /* hash table */ - $s = $st['t']; - if(JAVA_DEBUG) {echo "setresult prepare hash:"; echo sprintf("%s", $st['t']); echo "\n";} - if($s[0]=='N') { /* number */ - $arg->setIndex($this->getExact($st['v'])); - if(JAVA_DEBUG) {echo "setresult array: index:"; echo sprintf("%s", $st['v']); echo "\n";} - } else { - $arg->setIndex($this->parser->getData($st['v'])); - if(JAVA_DEBUG) {echo "setresult hash: index:"; echo sprintf("%s", $this->parser->getData($st['v'])); echo "\n";} - } - } else { /* array */ - $arg->setNextIndex(); - } - break; - case 'S': - $arg->setResult($this->parser->getData($st['v'])); - if(JAVA_DEBUG) {echo "setresult string:"; echo sprintf("%s", $this->parser->getData($st['v'])); echo "\n";} - break; - case 'B': - $s=$st['v']; - $arg->setResult($s[0]=='T'); - if(JAVA_DEBUG) {echo "setresult bool:"; echo sprintf("%s", $st['v']); echo "\n";} - break; - case 'L': // unsigned long - $sign = $st['p']; - $val = $this->getExact($st['v']); - if($sign[0]=='A') $val*=-1; - $arg->setResult($val); - if(JAVA_DEBUG) {echo "setresult long:"; echo sprintf("%s, sign: %s", $st['v'], $st['p']); echo "\n";} - break; - case 'D': - $arg->setResult($this->getInexact($st['v'])); - if(JAVA_DEBUG) {echo "setresult double:"; echo sprintf("%s", $st['v']); echo "\n";} - break; - case 'V': - if ($st['n']!='T') { - if(JAVA_DEBUG) {echo "setresult VOID:"; echo "\n";} - $arg->setVoidSignature(); - } - // fall through - case 'N': - $arg->setResult(null); - if(JAVA_DEBUG) {echo "setresult null\n"; } - break; - case 'F': - if(JAVA_DEBUG) {echo "comm. end\n"; } - break; - case 'O': - $arg->setFactory($this->getProxyFactory($st['p'])); - $arg->setResult($this->asyncCtx=$this->getExact($st['v'])); - if($st['n']!='T') $arg->setSignature($st['m']); - if(JAVA_DEBUG) {echo "setresult object:"; echo sprintf("%x", $this->asyncCtx); echo "\n";} - break; - case 'E': - $arg->setFactory($this->throwExceptionProxyFactory); - if(JAVA_DEBUG) {echo "setresult exception:"; echo sprintf("%x", $this->asyncCtx); echo "\n";} - $arg->setException($st['m']); - $arg->setResult($this->asyncCtx=$this->getExact($st['v'])); - break; - default: - $this->parser->parserError(); - } - } - function end($name) { - switch($name[0]) { - case 'X': - $frame = array_pop($this->stack); - $this->arg = $frame->parentArg; - break; - } - } - function createParserString() { - return new java_ParserString(); - } - - function writeArg($arg) { - if(is_string($arg)) { - $this->protocol->writeString($arg); - } else if(is_object($arg)) { - if ((!$arg instanceof java_JavaType)) { - error_log((string)new java_IllegalArgumentException($arg)); - trigger_error("argument '".get_class($arg)."' is not a Java object, using NULL instead", E_USER_WARNING); - $this->protocol->writeObject(null); - } else { - $this->protocol->writeObject($arg->__java); - } - } else if(is_null($arg)) { - $this->protocol->writeObject(null); - } else if(is_bool($arg)) { - $this->protocol->writeBoolean($arg); - } else if(is_integer($arg)) { - $this->protocol->writeLong($arg); - } else if(is_float($arg)) { - $this->protocol->writeDouble($arg); - } else if(is_array($arg)) { - $wrote_begin=false; - foreach($arg as $key=>$val) { - if(is_string($key)) { - if(!$wrote_begin) { - $wrote_begin=1; - $this->protocol->writeCompositeBegin_h(); - } - $this->protocol->writePairBegin_s($key); - $this->writeArg($val); - $this->protocol->writePairEnd(); - } else { - if(!$wrote_begin) { - $wrote_begin=1; - $this->protocol->writeCompositeBegin_h(); - } - $this->protocol->writePairBegin_n($key); - $this->writeArg($val); - $this->protocol->writePairEnd(); - } - } - if(!$wrote_begin) { - $this->protocol->writeCompositeBegin_a(); - } - $this->protocol->writeCompositeEnd(); - } - } - function writeArgs($args) { - $this->inArgs = true; - $n = count($args); - for($i=0; $i<$n; $i++) { - $this->writeArg($args[$i]); - } - $this->inArgs = false; - } - function createObject($name, $args) { - $this->protocol->createObjectBegin($name); - $this->writeArgs($args); - $this->protocol->createObjectEnd(); - $val = $this->getInternalResult(); - return $val; - } - function referenceObject($name, $args) { - $this->protocol->referenceBegin($name); - $this->writeArgs($args); - $this->protocol->referenceEnd(); - $val = $this->getInternalResult(); - return $val; - } - function getProperty($object, $property) { - $this->protocol->propertyAccessBegin($object, $property); - $this->protocol->propertyAccessEnd(); - return $this->getResult(); - } - function setProperty($object, $property, $arg) { - $this->protocol->propertyAccessBegin($object, $property); - $this->writeArg($arg); - $this->protocol->propertyAccessEnd(); - $this->getResult(); - } - function invokeMethod($object, $method, $args) { - $this->protocol->invokeBegin($object, $method); - $this->writeArgs($args); - $this->protocol->invokeEnd(); - $val = $this->getResult(); - return $val; - } - function unref($object) { - if (isset($this->protocol)) $this->protocol->writeUnref($object); - } - function apply($arg) { - $name = $arg->p; - $object = $arg->v; - $ob = ($object==null) ? $name : array(&$object, $name); - - // save the current state - $isAsync = $this->isAsync; - $methodCache = $this->methodCache; - $currentArgumentsFormat = $this->currentArgumentsFormat; - // the currentCacheKey is destroyed when the result is received - // so that apply calls are not cached - - try { - $res = $arg->getResult(true); - if((($object==null) && !function_exists($name)) || (!($object==null) && !method_exists($object, $name))) throw new JavaException("java.lang.NoSuchMethodError", "$name"); - - $res = call_user_func_array($ob, $res); - - if (is_object($res) && (!($res instanceof java_JavaType))) { - trigger_error("object returned from $name() is not a Java object", E_USER_WARNING); - - // correct this error by calling: $res=java_closure($res); - $this->protocol->invokeBegin(0, "makeClosure"); - $this->protocol->writeULong($this->globalRef->add($res)); // proper PHP "long" -> Java 64 bit value conversion - $this->protocol->invokeEnd(); - $res = $this->getResult(); - } - - $this->protocol->resultBegin(); - $this->writeArg($res); - $this->protocol->resultEnd(); - } catch (JavaException $e) { - $trace = $e->getTraceAsString(); - $this->protocol->resultBegin(); - $this->protocol->writeException($e->__java, $trace); - $this->protocol->resultEnd(); - } catch(Exception $ex) { - error_log($ex->__toString()); - trigger_error("Unchecked exception detected in callback", E_USER_ERROR); - die (1); - } - - // restore the state - $this->isAsync = $isAsync; - $this->methodCache = $methodCache; - $this->currentArgumentsFormat = $currentArgumentsFormat; - } - function cast($object, $type) { - switch($type[0]) { - case 'S': case 's': - return $this->invokeMethod(0, "castToString", array($object)); - case 'B': case 'b': - return $this->invokeMethod(0, "castToBoolean", array($object)); - case 'L': case 'I': case 'l': case 'i': - return $this->invokeMethod(0, "castToExact", array($object)); - case 'D': case 'd': case 'F': case 'f': - return $this->invokeMethod(0, "castToInExact", array($object)); - case 'N': case 'n': - return null; - case 'A': case 'a': - return $this->invokeMethod(0, "castToArray", array($object)); - case 'O': case 'o': // eh? - return $object; - default: - throw new java_RuntimeException("$type illegal"); - } - } - function getContext() { - static $cache = null; - if (!is_null($cache)) return $cache; - return $cache = $this->invokeMethod(0, "getContext", array()); - } - function getSession($args) { - return $this->invokeMethod(0, "getSession", $args); - } - function getServerName() { - static $cache = null; - if (!is_null($cache)) return $cache; - return $cache = $this->protocol->getServerName(); - } + public $RUNTIME; + + public $result, $exception; + public $parser; + + public $simpleArg, $compositeArg; + public $simpleFactory, + $proxyFactory, $iteratorProxyFacroty, + $arrayProxyFactory, $exceptionProxyFactory, $throwExceptionProxyFactory; + + public $arg; + public $asyncCtx, $cancelProxyCreationTag; + public $globalRef; + + public $stack; + + // the cache + public $defaultCache = array(), $asyncCache = array(), $methodCache; + public $isAsync = 0; + public $currentCacheKey, $currentArgumentsFormat; + public $cachedJavaPrototype; + + + // send buffer + public $sendBuffer, $preparedToSendBuffer; + + // do not finish protocol if ags construction fails due to PHP OutOfMemory error + public $inArgs; + + function __construct() { + $this->RUNTIME = array(); + $this->RUNTIME["NOTICE"]='***USE echo java_inspect(jVal) OR print_r(java_values(jVal)) TO SEE THE CONTENTS OF THIS JAVA OBJECT!***'; + + $this->parser = new java_Parser($this); + $this->protocol = new java_Protocol($this); + + $this->simpleFactory = new java_SimpleFactory($this); + $this->proxyFactory = new java_ProxyFactory($this); + $this->arrayProxyFactory = new java_ArrayProxyFactory($this); + $this->iteratorProxyFactory = new java_IteratorProxyFactory($this); + $this->exceptionProxyFactory = new java_ExceptionProxyFactory($this); + $this->throwExceptionProxyFactory = new java_ThrowExceptionProxyFactory($this); + + $this->cachedJavaPrototype=new java_JavaProxyProxy($this); + + $this->simpleArg = new java_Arg($this); + + $this->globalRef = new java_GlobalRef(); + + $this->asyncCtx = $this->cancelProxyCreationTag = 0; + + $this->methodCache = $this->defaultCache; + + $this->inArgs = false; + } + + function read($size) { + return $this->protocol->read($size); + } + + function setDefaultHandler() { + $this->methodCache = $this->defaultCache; + } + + function setAsyncHandler() { + $this->methodCache = $this->asyncCache; + } + + + function handleRequests() { + $tail_call = false; + do { + $this->stack=array($this->arg=$this->simpleArg); + $this->idx = 0; + $this->parser->parse(); + + /* pull off A, if any */ + if((count($this->stack)) > 1) { + $arg = array_pop($this->stack); + $this->apply($arg); + $tail_call = true; // we don't expect a result + } else { + $tail_call = false; + } + + $this->stack=null; + } while($tail_call); + return 1; + } + + function getWrappedResult($wrap) { + return $this->simpleArg->getResult($wrap); + } + function getInternalResult() { + return $this->getWrappedResult(false); + } + function getResult() { + return $this->getWrappedResult(true); + } + function getProxyFactory($type) { + switch($type[0]) { + case 'E': + $factory = $this->exceptionProxyFactory; + break; + case 'C': + $factory = $this->iteratorProxyFactory; + break; + case 'A': + $factory = $this->arrayProxyFactory; + break; + default: + case 'O': + $factory = $this->proxyFactory; + } + return $factory; + } + function link(&$arg, &$newArg) { + $arg->linkResult($newArg->val); + $newArg->parentArg = $arg; + } + function getExact($str) { + return hexdec($str); + } + function getInexact($str) { + $val = null; + sscanf($str, "%e", $val); + return $val; + } + function begin($name, $st) { + $arg = $this->arg; + switch($name[0]) { + case 'A': /* receive apply args as normal array */ + $object = $this->globalRef->get($this->getExact($st['v'])); + $newArg = new java_ApplyArg($this, 'A', + $this->parser->getData($st['m']), + $this->parser->getData($st['p']), + $object, + $this->getExact($st['n'])); + $this->link($arg, $newArg); + array_push($this->stack, $this->arg = $newArg); + break; + case 'X': + $newArg = new java_CompositeArg($this, $st['t']); + $this->link($arg, $newArg); + array_push($this->stack, $this->arg = $newArg); + break; + case 'P': + if($arg->type=='H') { /* hash table */ + $s = $st['t']; + if(JAVA_DEBUG) {echo "setresult prepare hash:"; echo sprintf("%s", $st['t']); echo "\n";} + if($s[0]=='N') { /* number */ + $arg->setIndex($this->getExact($st['v'])); + if(JAVA_DEBUG) {echo "setresult array: index:"; echo sprintf("%s", $st['v']); echo "\n";} + } else { + $arg->setIndex($this->parser->getData($st['v'])); + if(JAVA_DEBUG) {echo "setresult hash: index:"; echo sprintf("%s", $this->parser->getData($st['v'])); echo "\n";} + } + } else { /* array */ + $arg->setNextIndex(); + } + break; + case 'S': + $arg->setResult($this->parser->getData($st['v'])); + if(JAVA_DEBUG) {echo "setresult string:"; echo sprintf("%s", $this->parser->getData($st['v'])); echo "\n";} + break; + case 'B': + $s=$st['v']; + $arg->setResult($s[0]=='T'); + if(JAVA_DEBUG) {echo "setresult bool:"; echo sprintf("%s", $st['v']); echo "\n";} + break; + case 'L': // unsigned long + $sign = $st['p']; + $val = $this->getExact($st['v']); + if($sign[0]=='A') $val*=-1; + $arg->setResult($val); + if(JAVA_DEBUG) {echo "setresult long:"; echo sprintf("%s, sign: %s", $st['v'], $st['p']); echo "\n";} + break; + case 'D': + $arg->setResult($this->getInexact($st['v'])); + if(JAVA_DEBUG) {echo "setresult double:"; echo sprintf("%s", $st['v']); echo "\n";} + break; + case 'V': + if ($st['n']!='T') { + if(JAVA_DEBUG) {echo "setresult VOID:"; echo "\n";} + $arg->setVoidSignature(); + } + // fall through + case 'N': + $arg->setResult(null); + if(JAVA_DEBUG) {echo "setresult null\n"; } + break; + case 'F': + if(JAVA_DEBUG) {echo "comm. end\n"; } + break; + case 'O': + $arg->setFactory($this->getProxyFactory($st['p'])); + $arg->setResult($this->asyncCtx=$this->getExact($st['v'])); + if($st['n']!='T') $arg->setSignature($st['m']); + if(JAVA_DEBUG) {echo "setresult object:"; echo sprintf("%x", $this->asyncCtx); echo "\n";} + break; + case 'E': + $arg->setFactory($this->throwExceptionProxyFactory); + if(JAVA_DEBUG) {echo "setresult exception:"; echo sprintf("%x", $this->asyncCtx); echo "\n";} + $arg->setException($st['m']); + $arg->setResult($this->asyncCtx=$this->getExact($st['v'])); + break; + default: + $this->parser->parserError(); + } + } + function end($name) { + switch($name[0]) { + case 'X': + $frame = array_pop($this->stack); + $this->arg = $frame->parentArg; + break; + } + } + function createParserString() { + return new java_ParserString(); + } + + function writeArg($arg) { + if(is_string($arg)) { + $this->protocol->writeString($arg); + } else if(is_object($arg)) { + if ((!$arg instanceof java_JavaType)) { + error_log((string)new java_IllegalArgumentException($arg)); + trigger_error("argument '".get_class($arg)."' is not a Java object, using NULL instead", E_USER_WARNING); + $this->protocol->writeObject(null); + } else { + $this->protocol->writeObject($arg->__java); + } + } else if(is_null($arg)) { + $this->protocol->writeObject(null); + } else if(is_bool($arg)) { + $this->protocol->writeBoolean($arg); + } else if(is_integer($arg)) { + $this->protocol->writeLong($arg); + } else if(is_float($arg)) { + $this->protocol->writeDouble($arg); + } else if(is_array($arg)) { + $wrote_begin=false; + foreach($arg as $key=>$val) { + if(is_string($key)) { + if(!$wrote_begin) { + $wrote_begin=1; + $this->protocol->writeCompositeBegin_h(); + } + $this->protocol->writePairBegin_s($key); + $this->writeArg($val); + $this->protocol->writePairEnd(); + } else { + if(!$wrote_begin) { + $wrote_begin=1; + $this->protocol->writeCompositeBegin_h(); + } + $this->protocol->writePairBegin_n($key); + $this->writeArg($val); + $this->protocol->writePairEnd(); + } + } + if(!$wrote_begin) { + $this->protocol->writeCompositeBegin_a(); + } + $this->protocol->writeCompositeEnd(); + } + } + function writeArgs($args) { + $this->inArgs = true; + $n = count($args); + for($i=0; $i<$n; $i++) { + $this->writeArg($args[$i]); + } + $this->inArgs = false; + } + function createObject($name, $args) { + $this->protocol->createObjectBegin($name); + $this->writeArgs($args); + $this->protocol->createObjectEnd(); + $val = $this->getInternalResult(); + return $val; + } + function referenceObject($name, $args) { + $this->protocol->referenceBegin($name); + $this->writeArgs($args); + $this->protocol->referenceEnd(); + $val = $this->getInternalResult(); + return $val; + } + function getProperty($object, $property) { + $this->protocol->propertyAccessBegin($object, $property); + $this->protocol->propertyAccessEnd(); + return $this->getResult(); + } + function setProperty($object, $property, $arg) { + $this->protocol->propertyAccessBegin($object, $property); + $this->writeArg($arg); + $this->protocol->propertyAccessEnd(); + $this->getResult(); + } + function invokeMethod($object, $method, $args) { + $this->protocol->invokeBegin($object, $method); + $this->writeArgs($args); + $this->protocol->invokeEnd(); + $val = $this->getResult(); + return $val; + } + function setExitCode($code) { + if (isset($this->protocol)) $this->protocol->writeExitCode($code); + } + function unref($object) { + if (isset($this->protocol)) $this->protocol->writeUnref($object); + } + function apply($arg) { + $name = $arg->p; + $object = $arg->v; + $ob = ($object==null) ? $name : array(&$object, $name); + + // save the current state + $isAsync = $this->isAsync; + $methodCache = $this->methodCache; + $currentArgumentsFormat = $this->currentArgumentsFormat; + // the currentCacheKey is destroyed when the result is received + // so that apply calls are not cached + + try { + $res = $arg->getResult(true); + if((($object==null) && !function_exists($name)) || (!($object==null) && !method_exists($object, $name))) throw new JavaException("java.lang.NoSuchMethodError", "$name"); + + $res = call_user_func_array($ob, $res); + + if (is_object($res) && (!($res instanceof java_JavaType))) { + trigger_error("object returned from $name() is not a Java object", E_USER_WARNING); + + // correct this error by calling: $res=java_closure($res); + $this->protocol->invokeBegin(0, "makeClosure"); + $this->protocol->writeULong($this->globalRef->add($res)); // proper PHP "long" -> Java 64 bit value conversion + $this->protocol->invokeEnd(); + $res = $this->getResult(); + } + + $this->protocol->resultBegin(); + $this->writeArg($res); + $this->protocol->resultEnd(); + } catch (JavaException $e) { + $trace = $e->getTraceAsString(); + $this->protocol->resultBegin(); + $this->protocol->writeException($e->__java, $trace); + $this->protocol->resultEnd(); + } catch(Exception $ex) { + error_log($ex->__toString()); + trigger_error("Unchecked exception detected in callback", E_USER_ERROR); + die (1); + } + + // restore the state + $this->isAsync = $isAsync; + $this->methodCache = $methodCache; + $this->currentArgumentsFormat = $currentArgumentsFormat; + } + function cast($object, $type) { + switch($type[0]) { + case 'S': case 's': + return $this->invokeMethod(0, "castToString", array($object)); + case 'B': case 'b': + return $this->invokeMethod(0, "castToBoolean", array($object)); + case 'L': case 'I': case 'l': case 'i': + return $this->invokeMethod(0, "castToExact", array($object)); + case 'D': case 'd': case 'F': case 'f': + return $this->invokeMethod(0, "castToInExact", array($object)); + case 'N': case 'n': + return null; + case 'A': case 'a': + return $this->invokeMethod(0, "castToArray", array($object)); + case 'O': case 'o': // eh? + return $object; + default: + throw new java_RuntimeException("$type illegal"); + } + } + function getContext() { + static $cache = null; + if (!is_null($cache)) return $cache; + return $cache = $this->invokeMethod(0, "getContext", array()); + } + function getSession($args) { + return $this->invokeMethod(0, "getSession", $args); + } + function getServerName() { + static $cache = null; + if (!is_null($cache)) return $cache; + return $cache = $this->protocol->getServerName(); + } } /** * @access private */ function java_shutdown() { - global $java_initialized; - if (!$java_initialized) return; - - if (session_id()) session_write_close(); - $client = __javaproxy_Client_getClient(); - if(JAVA_DEBUG) echo "the client destroyed\n"; - if (!isset($client->protocol) || $client->inArgs) return; - if ($client->preparedToSendBuffer) - $client->sendBuffer.=$client->preparedToSendBuffer; - $client->sendBuffer.=$client->protocol->getKeepAlive(); - $client->protocol->flush(); - $client->protocol->keepAlive(); + global $java_initialized; + if (!$java_initialized) return; + + if (session_id()) session_write_close(); + $client = __javaproxy_Client_getClient(); + if(JAVA_DEBUG) echo "the client destroyed\n"; + if (!isset($client->protocol) || $client->inArgs) return; + if ($client->preparedToSendBuffer) + $client->sendBuffer.=$client->preparedToSendBuffer; + $client->sendBuffer.=$client->protocol->getKeepAlive(); + $client->protocol->flush(); + $client->protocol->keepAlive(); } register_shutdown_function("java_shutdown"); diff --git a/legacy/server/META-INF/java/JavaProxy.inc b/legacy/server/META-INF/java/JavaProxy.inc index eef5ccd..637fffe 100644 --- a/legacy/server/META-INF/java/JavaProxy.inc +++ b/legacy/server/META-INF/java/JavaProxy.inc @@ -1,47 +1,47 @@ * define ("JAVA_PREFER_VALUES", false); * require_once("http://localhost:8080/JavaBridge/java/Java.inc"); * try { * new java("java.lang.String", null); // raises java.lang.RuntimeException - * assert (is_null(java_last_exception_get()); + * assert (is_null(java_last_exception_get()); * } catch (JavaException $e) { * echo $e; * } * * - * + * * @return mixed The last stored Java exception or null * @access public * @see java_last_exception_clear() * @see JAVA_PREFER_VALUES */ function java_last_exception_get() { - $client=__javaproxy_Client_getClient(); - return $client->invokeMethod(0, "getLastException", array()); + $client=__javaproxy_Client_getClient(); + return $client->invokeMethod(0, "getLastException", array()); } /** * Clear a stored Java exception. - * + * * @access public * @see java_last_exception_get() */ function java_last_exception_clear() { - $client=__javaproxy_Client_getClient(); - $client->invokeMethod(0, "clearLastException", array()); + $client=__javaproxy_Client_getClient(); + $client->invokeMethod(0, "clearLastException", array()); } /** * Only for internal use * @access private */ function java_values_internal($object) { - if(!$object instanceof java_JavaType) return $object; - $client=__javaproxy_Client_getClient(); - return $client->invokeMethod(0, "getValues", array($object)); + if(!$object instanceof java_JavaType) return $object; + $client=__javaproxy_Client_getClient(); + return $client->invokeMethod(0, "getValues", array($object)); } /** - * Invoke a method dynamically. - + * Invoke a method dynamically. + * Example: * * java_invoke(new java("java.lang.String","hello"), "toString", array()) @@ -157,14 +157,14 @@ function java_values_internal($object) { * @param array A argument array */ function java_invoke($object, $method, $args) { - $client=__javaproxy_Client_getClient(); - $id = ($object==null) ? 0 : $object->__java; - return $client->invokeMethod($id, $method, $args); + $client=__javaproxy_Client_getClient(); + $id = ($object==null) ? 0 : $object->__java; + return $client->invokeMethod($id, $method, $args); } /** * Unwrap a Java object. - * + * * Fetches the PHP object which has been wrapped by java_closure(). Example: * * class foo { function __toString() {return "php"; } function toString() {return "java";} } @@ -177,21 +177,21 @@ function java_invoke($object, $method, $args) { * */ function java_unwrap ($object) { - if(!$object instanceof java_JavaType) throw new java_IllegalArgumentException($object); - $client=__javaproxy_Client_getClient(); - return $client->globalRef->get($client->invokeMethod(0, "unwrapClosure", array($object))); -} + if(!$object instanceof java_JavaType) throw new java_IllegalArgumentException($object); + $client=__javaproxy_Client_getClient(); + return $client->globalRef->get($client->invokeMethod(0, "unwrapClosure", array($object))); +} /** * Evaluate a Java object. - * + * * Evaluate a object and fetch its content, if possible. Use java_values() to convert a Java object into an equivalent PHP value. * * A java array, Map or Collection object is returned * as a php array. An array, Map or Collection proxy is returned as a java array, Map or Collection object, and a null proxy is returned as null. All values of java types for which a primitive php type exists are returned as php values. Everything else is returned unevaluated. Please make sure that the values do not not exceed * php's memory limit. Example: * - * + * * * $str = new java("java.lang.String", "hello"); * echo java_values($str); @@ -207,30 +207,30 @@ function java_unwrap ($object) { * print java_values($ar[0]); * => h * - * + * * @see java_closure() * @param object A java object or type. * @access public */ function java_values($object) { - return java_values_internal($object); + return java_values_internal($object); } /** * Only for internal use. * @access private */ function java_reset() { - $client=__javaproxy_Client_getClient(); - return $client->invokeMethod(0, "reset", array()); + $client=__javaproxy_Client_getClient(); + return $client->invokeMethod(0, "reset", array()); } /** * Only for internal use * @access private */ function java_inspect_internal($object) { - if(!$object instanceof java_JavaType) throw new java_IllegalArgumentException($object); - $client=__javaproxy_Client_getClient(); - return $client->invokeMethod(0, "inspect", array($object)); + if(!$object instanceof java_JavaType) throw new java_IllegalArgumentException($object); + $client=__javaproxy_Client_getClient(); + return $client->invokeMethod(0, "inspect", array($object)); } /** * Returns the contents (public fields, public methods, public @@ -244,14 +244,14 @@ function java_inspect_internal($object) { * @access public */ function java_inspect($object) { - return java_inspect_internal($object); + return java_inspect_internal($object); } /** * 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: + * conversions use this encoding. Example: * * java_set_file_encoding("ISO-8859-1"); * @@ -262,64 +262,64 @@ function java_inspect($object) { * @access public */ function java_set_file_encoding($enc) { - $client=__javaproxy_Client_getClient(); - return $client->invokeMethod(0, "setFileEncoding", array($enc)); + $client=__javaproxy_Client_getClient(); + return $client->invokeMethod(0, "setFileEncoding", array($enc)); } /** * Only for internal use * @access private */ function java_instanceof_internal($ob, $clazz) { - if(!$ob instanceof java_JavaType) throw new java_IllegalArgumentException($ob); - if(!$clazz instanceof java_JavaType) throw new java_IllegalArgumentException($clazz); - $client=__javaproxy_Client_getClient(); - return $client->invokeMethod(0, "instanceOf", array($ob, $clazz)); + if(!$ob instanceof java_JavaType) throw new java_IllegalArgumentException($ob); + if(!$clazz instanceof java_JavaType) throw new java_IllegalArgumentException($clazz); + $client=__javaproxy_Client_getClient(); + return $client->invokeMethod(0, "instanceOf", array($ob, $clazz)); } /** * Tests if object is an instance of clazz. * - * Example: + * Example: * - * return($o instanceof Java && $c instanceof Java && java_instanceof($o, $c)); + * return($o instanceof Java && $c instanceof Java && java_instanceof($o, $c)); * * @param object A java object * @param object A java object or type. * @access public */ function java_instanceof($ob, $clazz) { - return java_instanceof_internal($ob, $clazz); + return java_instanceof_internal($ob, $clazz); } /** * Only for internal use * @access private */ -function java_cast_internal($object, $type) { +function java_cast_internal($object, $type) { if(!$object instanceof java_JavaType) { - switch($type[0]) { - case 'S': case 's': - return (string)$object; - case 'B': case 'b': - return (boolean)$object; - case 'L': case 'I': case 'l': case 'i': - return (integer)$object; - case 'D': case 'd': case 'F': case 'f': - return (float) $object; - case 'N': case 'n': - return null; - case 'A': case 'a': - return (array)$object; - case 'O': case 'o': - return (object)$object; - } - } - return $object->__cast($type); + switch($type[0]) { + case 'S': case 's': + return (string)$object; + case 'B': case 'b': + return (boolean)$object; + case 'L': case 'I': case 'l': case 'i': + return (integer)$object; + case 'D': case 'd': case 'F': case 'f': + return (float) $object; + case 'N': case 'n': + return null; + case 'A': case 'a': + return (array)$object; + case 'O': case 'o': + return (object)$object; + } + } + return $object->__cast($type); } /** - * Converts the java object obj into a PHP value. + * Converts the java object obj into a PHP value. * * This procedure converts the Java argument and then calls java_values() to fetch * its content. Use java_values() if the conversion is not necessary. - * + * * The second argument * must be [s]tring, [b]oolean, [i]nteger, [f]loat or [d]ouble, * [a]rray, [n]ull or [o]bject (which does nothing). @@ -345,8 +345,8 @@ function java_cast_internal($object, $type) { * @param string A PHP type description, either [Ss]tring, [Bb]oolean, [Ll]ong or [Ii]nteger, [Dd]ouble or [Ff]loat, [Nn]ull, [Aa]rray, [Oo]bject. * @access public */ -function java_cast($object, $type) { - return java_cast_internal($object, $type); +function java_cast($object, $type) { + return java_cast_internal($object, $type); } /** @@ -355,46 +355,46 @@ function java_cast($object, $type) { * @access private */ function java_require($arg) { - trigger_error('java_require() not supported anymore. Please use getSession($args); + if(!isset($args[1])) + $args[1]=0; // ISession.SESSION_GET_OR_CREATE + elseif ($args[1]===true) + $args[1]=1; // ISession.SESSION_CREATE_NEW + else + $args[1]=2; // ISession.SESSION_GET + + if(!isset($args[2])) { + $args[2] = java_get_lifetime (); + } + return $client->getSession($args); } /** * Return a session handle. * - * When java_session() is called without + * When java_session() is called without * arguments, the session is shared with java. - * Example: + * Example: * * java_session()->put("key", new Java("java.lang.Object")); * [...] @@ -432,7 +432,7 @@ function java_session_array($args) { * @see java_context() */ function java_session() { - return java_session_array(func_get_args()); + return java_session_array(func_get_args()); } /** @@ -445,14 +445,14 @@ function java_session() { * echo "Connected to the back-end: $backend\n"; * * @access public -*/ + */ function java_server_name() { - try { - $client=__javaproxy_Client_getClient(); - return $client->getServerName(); - } catch (java_ConnectException $ex) { - return null; - } + try { + $client=__javaproxy_Client_getClient(); + return $client->getServerName(); + } catch (java_ConnectException $ex) { + return null; + } } /** @@ -465,10 +465,10 @@ function java_server_name() { * Java with engine.get("key"). The get/put methods are convenience shortcuts for getAttribute/setAttribute. Example: * * engine.put("key1", 2); - * engine.eval("put("key2", 1+(int)(string)java_context()->get('key1'));?>"); + * engine.eval("put("key2", 1+(int)(string)java_context()->get('key1'));?>"); * System.out.println(engine.get("key2")); * - * + * * A synchronized init() procedure can be called from the context to initialize a library once, and a shutdown hook can be registered to destroy the library before the (web-) context is destroyed. The init hook can be written in PHP, but the shutdown hook must be written in Java. Example: * * function getShutdownHook() { return java("myJavaHelper")->getShutdownHook(); } @@ -479,7 +479,7 @@ function java_server_name() { * } * java_context()->init(java_closure(null, null, java("java.util.concurrent.Callable"))); * - * + * * It is possible to access implicit web objects (the session, the * application store etc.) from the context. Example: * @@ -508,12 +508,12 @@ function java_server_name() { * $ctx = java_context(); * if(java_is_false($ctx->call(java_closure()))) die "Script should be called from java"; * - * - * A second example which shows how to invoke PHP methods without the JSR 223 getInterface() and invokeMethod() + * + * A second example which shows how to invoke PHP methods without the JSR 223 getInterface() and invokeMethod() * helper procedures. The Java code can fetch the current PHP continuation from the context using the key "php.java.bridge.PhpProcedure": * * String s = "call(java_closure(new Runnable(), null, $Runnable)); @@ -529,40 +529,40 @@ function java_server_name() { * @see java_session() */ function java_context() { - $client=__javaproxy_Client_getClient(); - return $client->getContext(); + $client=__javaproxy_Client_getClient(); + return $client->getContext(); } /** * Only for internal use * @access private */ function java_closure_array($args) { - if(isset($args[2]) && ((!($args[2] instanceof java_JavaType))&&!is_array($args[2]))) - throw new java_IllegalArgumentException($args[2]); + if(isset($args[2]) && ((!($args[2] instanceof java_JavaType))&&!is_array($args[2]))) + throw new java_IllegalArgumentException($args[2]); - $client=__javaproxy_Client_getClient(); - $args[0] = isset($args[0]) ? $client->globalRef->add($args[0]) : 0; + $client=__javaproxy_Client_getClient(); + $args[0] = isset($args[0]) ? $client->globalRef->add($args[0]) : 0; - /* The following is identical to - return $client->invokeMethod(0, "makeClosure", $args); - except that the ref (args[0]) must be an unsigned value */ - $client->protocol->invokeBegin(0, "makeClosure"); - $n = count($args); - $client->protocol->writeULong($args[0]); // proper PHP "long" -> Java 64 bit value conversion - for($i=1; $i<$n; $i++) { - $client->writeArg($args[$i]); - } - $client->protocol->invokeEnd(); - $val = $client->getResult(); - return $val; + /* The following is identical to + return $client->invokeMethod(0, "makeClosure", $args); + except that the ref (args[0]) must be an unsigned value */ + $client->protocol->invokeBegin(0, "makeClosure"); + $n = count($args); + $client->protocol->writeULong($args[0]); // proper PHP "long" -> Java 64 bit value conversion + for($i=1; $i<$n; $i++) { + $client->writeArg($args[$i]); + } + $client->protocol->invokeEnd(); + $val = $client->getResult(); + return $val; } /** * Wraps a PHP environment. - * + * * Closes over the php environment and packages it up as a java * class. Use java_closure() to convert a PHP object into an equivalent Java object. * - * Example: + * Example: * * function toString() {return "helloWorld";}; * $object = java_closure(); @@ -576,7 +576,7 @@ function java_closure_array($args) { * function hello() {return "hello";}; * echo (string)java_closure(null, "hello"); * - * + * * When an array of java interfaces is supplied as a third argument, * the environment must implement these interfaces. * Example: @@ -594,14 +594,14 @@ function java_closure_array($args) { * @access public */ function java_closure() { - return java_closure_array(func_get_args()); + return java_closure_array(func_get_args()); } /** - * Enters stream mode (asynchronuous protocol). + * Enters stream mode (asynchronuous protocol). * * The statements are - * sent to the back-end in one XML stream. + * sent to the back-end in one XML stream. * * Use this protocol * mode when you have a large number of set operations and you don't @@ -613,8 +613,8 @@ function java_closure() { function java_begin_document() { } /** - * Ends stream mode. - * + * Ends stream mode. + * * Fires a JavaException if any statement executed during * stream mode raised an exception. * @deprecated @@ -627,120 +627,120 @@ function java_end_document() { * @access private */ class java_JavaProxy implements java_JavaType { - public $__serialID, $__java; - public $__signature; - public $__client; - public $__tempGlobalRef; + public $__serialID, $__java; + public $__signature; + public $__client; + public $__tempGlobalRef; - function __construct($java, $signature){ - $this->__java=$java; - $this->__signature=$signature; - $this->__client = __javaproxy_Client_getClient(); - } - function __cast($type) { - return $this->__client->cast($this, $type); - } - function __sleep() { - $args = array($this, java_get_lifetime()); - $this->__serialID = $this->__client->invokeMethod(0, "serialize", $args); - $this->__tempGlobalRef = $this->__client->globalRef; - if(JAVA_DEBUG) echo "proxy sleep called for $this->__java, $this->__signature\n"; - return array("__serialID", "__tempGlobalRef"); - } - function __wakeup() { - $args = array($this->__serialID, java_get_lifetime()); - if(JAVA_DEBUG) echo "proxy wakeup called for $this->__java, $this->__signature\n"; - $this->__client = __javaproxy_Client_getClient(); - if($this->__tempGlobalRef) - $this->__client->globalRef = $this->__tempGlobalRef; - $this->__tempGlobalRef = null; - $this->__java = $this->__client->invokeMethod(0, "deserialize", $args); - } - function __destruct() { - if(isset($this->__client)) - $this->__client->unref($this->__java); - } - function __get($key) { - return $this->__client->getProperty($this->__java, $key); - } - function __set($key, $val) { - $this->__client->setProperty($this->__java, $key, $val); - } - function __call($method, $args) { - return $this->__client->invokeMethod($this->__java, $method, $args); - } - function __toString() { - try { - return $this->__client->invokeMethod(0,"ObjectToString",array($this)); - } catch (JavaException $ex) { - trigger_error("Exception in Java::__toString(): ". java_truncate((string)$ex), E_USER_WARNING); - return ""; + function __construct($java, $signature){ + $this->__java=$java; + $this->__signature=$signature; + $this->__client = __javaproxy_Client_getClient(); + } + function __cast($type) { + return $this->__client->cast($this, $type); + } + function __sleep() { + $args = array($this, java_get_lifetime()); + $this->__serialID = $this->__client->invokeMethod(0, "serialize", $args); + $this->__tempGlobalRef = $this->__client->globalRef; + if(JAVA_DEBUG) echo "proxy sleep called for $this->__java, $this->__signature\n"; + return array("__serialID", "__tempGlobalRef"); + } + function __wakeup() { + $args = array($this->__serialID, java_get_lifetime()); + if(JAVA_DEBUG) echo "proxy wakeup called for $this->__java, $this->__signature\n"; + $this->__client = __javaproxy_Client_getClient(); + if($this->__tempGlobalRef) + $this->__client->globalRef = $this->__tempGlobalRef; + $this->__tempGlobalRef = null; + $this->__java = $this->__client->invokeMethod(0, "deserialize", $args); + } + function __destruct() { + if(isset($this->__client)) + $this->__client->unref($this->__java); + } + function __get($key) { + return $this->__client->getProperty($this->__java, $key); + } + function __set($key, $val) { + $this->__client->setProperty($this->__java, $key, $val); + } + function __call($method, $args) { + return $this->__client->invokeMethod($this->__java, $method, $args); + } + function __toString() { + try { + return $this->__client->invokeMethod(0,"ObjectToString",array($this)); + } catch (JavaException $ex) { + trigger_error("Exception in Java::__toString(): ". java_truncate((string)$ex), E_USER_WARNING); + return ""; + } } - } } /** * @access private */ class java_objectIterator implements Iterator { - private $var; + private $var; - function __construct($javaProxy) { - $this->var = java_cast ($javaProxy, "A"); - } - function rewind() { - reset($this->var); - } - function valid() { - return $this->current() !== false; - } - function next() { - return next($this->var); - } - function key() { - return key($this->var); - } - function current() { - return current($this->var); - } + function __construct($javaProxy) { + $this->var = java_cast ($javaProxy, "A"); + } + function rewind() { + reset($this->var); + } + function valid() { + return $this->current() !== false; + } + function next() { + return next($this->var); + } + function key() { + return key($this->var); + } + function current() { + return current($this->var); + } } /** * @access private */ class java_IteratorProxy extends java_JavaProxy implements IteratorAggregate { - function getIterator() { - return new java_ObjectIterator($this); - } + function getIterator() { + return new java_ObjectIterator($this); + } } /** * @access private */ class java_ArrayProxy extends java_IteratorProxy implements ArrayAccess { - function offsetExists($idx) { - $ar = array($this, $idx); - return $this->__client->invokeMethod(0,"offsetExists", $ar); - } - function offsetGet($idx) { - $ar = array($this, $idx); - return $this->__client->invokeMethod(0,"offsetGet", $ar); - } - function offsetSet($idx, $val) { - $ar = array($this, $idx, $val); - return $this->__client->invokeMethod(0,"offsetSet", $ar); - } - function offsetUnset($idx) { - $ar = array($this, $idx); - return $this->__client->invokeMethod(0,"offsetUnset", $ar); - } + function offsetExists($idx) { + $ar = array($this, $idx); + return $this->__client->invokeMethod(0,"offsetExists", $ar); + } + function offsetGet($idx) { + $ar = array($this, $idx); + return $this->__client->invokeMethod(0,"offsetGet", $ar); + } + function offsetSet($idx, $val) { + $ar = array($this, $idx, $val); + return $this->__client->invokeMethod(0,"offsetSet", $ar); + } + function offsetUnset($idx) { + $ar = array($this, $idx); + return $this->__client->invokeMethod(0,"offsetUnset", $ar); + } } /** * @access private */ class java_ExceptionProxy extends java_JavaProxy { - function __toExceptionString($trace) { - $args = array($this, $trace); - return $this->__client->invokeMethod(0,"ObjectToString",$args); - } + function __toExceptionString($trace) { + $args = array($this, $trace); + return $this->__client->invokeMethod(0,"ObjectToString",$args); + } } /** * This decorator/bridge overrides all magic methods and delegates to @@ -753,91 +753,91 @@ class java_ExceptionProxy extends java_JavaProxy { * * The constructor is an exception. If it is called, the user has * already allocated Java, so that $wrap is false and the proxy is - * returned and set into $__delegate. + * returned and set into $__delegate. * @access private * @see java_InternalJava -*/ + */ abstract class java_AbstractJava implements IteratorAggregate,ArrayAccess,java_JavaType { - public $__client; - - public $__delegate; + public $__client; - public $__serialID; + public $__delegate; - public $__factory; - public $__java, $__signature; + public $__serialID; - public $__cancelProxyCreationTag; + public $__factory; + public $__java, $__signature; - function __createDelegate() { - $proxy = $this->__delegate = - $this->__factory->create($this->__java, $this->__signature); - $this->__java = $proxy->__java; - $this->__signature = $proxy->__signature; - } - function __cast($type) { - if(!isset($this->__delegate)) $this->__createDelegate(); - return $this->__delegate->__cast($type); - } - function __sleep() { - if(!isset($this->__delegate)) $this->__createDelegate(); - $this->__delegate->__sleep(); - return array("__delegate"); - } - function __wakeup() { - if(!isset($this->__delegate)) $this->__createDelegate(); - $this->__delegate->__wakeup(); - $this->__java = $this->__delegate->__java; - $this->__client = $this->__delegate->__client; - } - function __get($key) { - if(!isset($this->__delegate)) $this->__createDelegate(); - return $this->__delegate->__get($key); - } - function __set($key, $val) { - if(!isset($this->__delegate)) $this->__createDelegate(); - $this->__delegate->__set($key, $val); - } - function __call($method, $args) { - if(!isset($this->__delegate)) $this->__createDelegate(); - return $this->__delegate->__call($method, $args); - } - function __toString() { - if(!isset($this->__delegate)) $this->__createDelegate(); - return $this->__delegate->__toString(); - } + public $__cancelProxyCreationTag; - // The following functions are for backward compatibility - function getIterator() { - if(!isset($this->__delegate)) $this->__createDelegate(); - if(func_num_args()==0) return $this->__delegate->getIterator(); - $args = func_get_args(); return $this->__call("getIterator", $args); - } - function offsetExists($idx) { - if(!isset($this->__delegate)) $this->__createDelegate(); - if(func_num_args()==1) return $this->__delegate->offsetExists($idx); - $args = func_get_args(); return $this->__call("offsetExists", $args); - } - function offsetGet($idx) { - if(!isset($this->__delegate)) $this->__createDelegate(); - if(func_num_args()==1) return $this->__delegate->offsetGet($idx); - $args = func_get_args(); return $this->__call("offsetGet", $args); - } - function offsetSet($idx, $val) { - if(!isset($this->__delegate)) $this->__createDelegate(); - if(func_num_args()==2) return $this->__delegate->offsetSet($idx, $val); - $args = func_get_args(); return $this->__call("offsetSet", $args); - } - function offsetUnset($idx) { - if(!isset($this->__delegate)) $this->__createDelegate(); - if(func_num_args()==1) return $this->__delegate->offsetUnset($idx); - $args = func_get_args(); return $this->__call("offsetUnset", $args); - } + function __createDelegate() { + $proxy = $this->__delegate = + $this->__factory->create($this->__java, $this->__signature); + $this->__java = $proxy->__java; + $this->__signature = $proxy->__signature; + } + function __cast($type) { + if(!isset($this->__delegate)) $this->__createDelegate(); + return $this->__delegate->__cast($type); + } + function __sleep() { + if(!isset($this->__delegate)) $this->__createDelegate(); + $this->__delegate->__sleep(); + return array("__delegate"); + } + function __wakeup() { + if(!isset($this->__delegate)) $this->__createDelegate(); + $this->__delegate->__wakeup(); + $this->__java = $this->__delegate->__java; + $this->__client = $this->__delegate->__client; + } + function __get($key) { + if(!isset($this->__delegate)) $this->__createDelegate(); + return $this->__delegate->__get($key); + } + function __set($key, $val) { + if(!isset($this->__delegate)) $this->__createDelegate(); + $this->__delegate->__set($key, $val); + } + function __call($method, $args) { + if(!isset($this->__delegate)) $this->__createDelegate(); + return $this->__delegate->__call($method, $args); + } + function __toString() { + if(!isset($this->__delegate)) $this->__createDelegate(); + return $this->__delegate->__toString(); + } + + // The following functions are for backward compatibility + function getIterator() { + if(!isset($this->__delegate)) $this->__createDelegate(); + if(func_num_args()==0) return $this->__delegate->getIterator(); + $args = func_get_args(); return $this->__call("getIterator", $args); + } + function offsetExists($idx) { + if(!isset($this->__delegate)) $this->__createDelegate(); + if(func_num_args()==1) return $this->__delegate->offsetExists($idx); + $args = func_get_args(); return $this->__call("offsetExists", $args); + } + function offsetGet($idx) { + if(!isset($this->__delegate)) $this->__createDelegate(); + if(func_num_args()==1) return $this->__delegate->offsetGet($idx); + $args = func_get_args(); return $this->__call("offsetGet", $args); + } + function offsetSet($idx, $val) { + if(!isset($this->__delegate)) $this->__createDelegate(); + if(func_num_args()==2) return $this->__delegate->offsetSet($idx, $val); + $args = func_get_args(); return $this->__call("offsetSet", $args); + } + function offsetUnset($idx) { + if(!isset($this->__delegate)) $this->__createDelegate(); + if(func_num_args()==1) return $this->__delegate->offsetUnset($idx); + $args = func_get_args(); return $this->__call("offsetUnset", $args); + } } /** * The Java proxy class. - * + * * Use this class to create a Java instance. Use the Java function to access a Java type. * * Example which creates an instance: @@ -855,240 +855,240 @@ abstract class java_AbstractJava implements IteratorAggregate,ArrayAccess,java_J * @see function Java */ class Java extends java_AbstractJava { - /** - * Create a new instance. - * - * This constructor can be - * used to create an instance of a Java class to access its - * features.
- * - * To access constants or procedures within a class, use the java function instead.
- * - * To convert a Java object into a PHP value, use the java_values() function.
- * - * Example which creates an instance: - * - * $s = new Java("java.lang.String", "hello"); - * - * - * Example which accesses the System class: - * - * $s = Java("java.lang.System"); - * - * - * If the option JAVA_PREFER_VALUES is set, Java values are automatically coerced to PHP values. - * Example which sets the option JAVA_PREFER_VALUES: - * - * define("JAVA_PREFER_VALUES", true); - * require_once("java/Java.inc"); - * ... - * if (java("java.lang.System")->getProperty("foo", false)) ... - * - * Otherwise java_values() must be used to fetch a PHP value from a Java object or Java value. - * The same example which usually executes 5 times faster: - * - * require_once("java/Java.inc"); - * ... - * if (java_values(java("java.lang.System")->getProperty("foo", false))) ... - * - * - * @see JAVA_PREFER_VALUES - * @see function Java - * @see function java_values - */ - function __construct() { - $client = $this->__client = __javaproxy_Client_getClient(); - - $args = func_get_args(); - $name = array_shift($args); + /** + * Create a new instance. + * + * This constructor can be + * used to create an instance of a Java class to access its + * features.
+ * + * To access constants or procedures within a class, use the java function instead.
+ * + * To convert a Java object into a PHP value, use the java_values() function.
+ * + * Example which creates an instance: + * + * $s = new Java("java.lang.String", "hello"); + * + * + * Example which accesses the System class: + * + * $s = Java("java.lang.System"); + * + * + * If the option JAVA_PREFER_VALUES is set, Java values are automatically coerced to PHP values. + * Example which sets the option JAVA_PREFER_VALUES: + * + * define("JAVA_PREFER_VALUES", true); + * require_once("java/Java.inc"); + * ... + * if (java("java.lang.System")->getProperty("foo", false)) ... + * + * Otherwise java_values() must be used to fetch a PHP value from a Java object or Java value. + * The same example which usually executes 5 times faster: + * + * require_once("java/Java.inc"); + * ... + * if (java_values(java("java.lang.System")->getProperty("foo", false))) ... + * + * + * @see JAVA_PREFER_VALUES + * @see function Java + * @see function java_values + */ + function __construct() { + $client = $this->__client = __javaproxy_Client_getClient(); - // compatibility with the C implementation - if(is_array($name)) {$args = $name; $name = array_shift($args);} + $args = func_get_args(); + $name = array_shift($args); - /* do not delete this line, it is used when generating Mono.inc from Java.inc */ + // compatibility with the C implementation + if(is_array($name)) {$args = $name; $name = array_shift($args);} - $sig="&{$this->__signature}@{$name}"; - $len = count($args); - $args2 = array(); - for($i=0; $i<$len; $i++) { - switch(gettype($val = $args[$i])) { - case 'boolean': array_push($args2, $val); $sig.='@b'; break; - case 'integer': array_push($args2, $val); $sig.='@i'; break; - case 'double': array_push($args2, $val); $sig.='@d'; break; - case 'string': array_push($args2, htmlspecialchars($val, ENT_COMPAT,"ISO-8859-1")); $sig.='@s'; break; - case 'array':$sig="~INVALID"; break; - case 'object': - if($val instanceof java_JavaType) { - array_push($args2, $val->__java); - $sig.="@o{$val->__signature}"; - } - else { - $sig="~INVALID"; - } - break; - case 'resource': array_push($args2, $val); $sig.='@r'; break; - case 'NULL': array_push($args2, $val); $sig.='@N'; break; - case 'unknown type': array_push($args2, $val); $sig.='@u'; break; - default: throw new java_IllegalArgumentException($val); - } - } + /* do not delete this line, it is used when generating Mono.inc from Java.inc */ - if(array_key_exists($sig, $client->methodCache)) { - if(JAVA_DEBUG) { echo "cache hit for new Java: $sig\n"; } - $cacheEntry = &$client->methodCache[$sig]; - $client->sendBuffer.= $client->preparedToSendBuffer; - if(strlen($client->sendBuffer)>=JAVA_SEND_SIZE) { - if($client->protocol->handler->write($client->sendBuffer)<=0) - throw new java_IllegalStateException("Connection out of sync, check backend log for details."); - $client->sendBuffer=null; - } - - $client->preparedToSendBuffer=vsprintf($cacheEntry->fmt, $args2); + $sig="&{$this->__signature}@{$name}"; + $len = count($args); + $args2 = array(); + for($i=0; $i<$len; $i++) { + switch(gettype($val = $args[$i])) { + case 'boolean': array_push($args2, $val); $sig.='@b'; break; + case 'integer': array_push($args2, $val); $sig.='@i'; break; + case 'double': array_push($args2, $val); $sig.='@d'; break; + case 'string': array_push($args2, htmlspecialchars($val, ENT_COMPAT,"ISO-8859-1")); $sig.='@s'; break; + case 'array':$sig="~INVALID"; break; + case 'object': + if($val instanceof java_JavaType) { + array_push($args2, $val->__java); + $sig.="@o{$val->__signature}"; + } + else { + $sig="~INVALID"; + } + break; + case 'resource': array_push($args2, $val); $sig.='@r'; break; + case 'NULL': array_push($args2, $val); $sig.='@N'; break; + case 'unknown type': array_push($args2, $val); $sig.='@u'; break; + default: throw new java_IllegalArgumentException($val); + } + } - if(JAVA_DEBUG) {print_r($args2); echo "set prepared to send buffer: $client->preparedToSendBuffer, $cacheEntry->fmt, for key: $sig\n";} - $this->__java = ++$client->asyncCtx; + if(array_key_exists($sig, $client->methodCache)) { + if(JAVA_DEBUG) { echo "cache hit for new Java: $sig\n"; } + $cacheEntry = &$client->methodCache[$sig]; + $client->sendBuffer.= $client->preparedToSendBuffer; + if(strlen($client->sendBuffer)>=JAVA_SEND_SIZE) { + if($client->protocol->handler->write($client->sendBuffer)<=0) + throw new java_IllegalStateException("Connection out of sync, check backend log for details."); + $client->sendBuffer=null; + } - if(JAVA_DEBUG) {echo "setresult from new Java cache: object:"; echo sprintf("%x", $client->asyncCtx); echo "\n";} - $this->__factory = $cacheEntry->factory; - $this->__signature = $cacheEntry->signature; + $client->preparedToSendBuffer=vsprintf($cacheEntry->fmt, $args2); - $this->__cancelProxyCreationTag = ++$client->cancelProxyCreationTag; - } else { - if(JAVA_DEBUG) { echo "cache miss for new Java: $sig\n"; } - $client->currentCacheKey = $sig; - $delegate = $this->__delegate = $client->createObject($name, $args); - $this->__java = $delegate->__java; - $this->__signature = $delegate->__signature; - } - } - /** @access private */ - function __destruct() { - if(!isset($this->__client)) return; - $client = $this->__client; + if(JAVA_DEBUG) {print_r($args2); echo "set prepared to send buffer: $client->preparedToSendBuffer, $cacheEntry->fmt, for key: $sig\n";} + $this->__java = ++$client->asyncCtx; - $preparedToSendBuffer = &$client->preparedToSendBuffer; + if(JAVA_DEBUG) {echo "setresult from new Java cache: object:"; echo sprintf("%x", $client->asyncCtx); echo "\n";} + $this->__factory = $cacheEntry->factory; + $this->__signature = $cacheEntry->signature; + + $this->__cancelProxyCreationTag = ++$client->cancelProxyCreationTag; + } else { + if(JAVA_DEBUG) { echo "cache miss for new Java: $sig\n"; } + $client->currentCacheKey = $sig; + $delegate = $this->__delegate = $client->createObject($name, $args); + $this->__java = $delegate->__java; + $this->__signature = $delegate->__signature; + } + } + /** @access private */ + function __destruct() { + if(!isset($this->__client)) return; + $client = $this->__client; - // Cancel proxy creation: If the created instance is collected - // before the next java statement is executed, we set the result - // type to void - if($preparedToSendBuffer && - $client->cancelProxyCreationTag==$this->__cancelProxyCreationTag) { + $preparedToSendBuffer = &$client->preparedToSendBuffer; - $preparedToSendBuffer[6]="3"; - if(JAVA_DEBUG) {echo "cancel result proxy creation:"; echo $this->__java; echo " {$client->preparedToSendBuffer}"; echo "\n";} - $client->sendBuffer.=$preparedToSendBuffer; - $preparedToSendBuffer = null; - $client->asyncCtx -= 1; - } else { - if(!isset($this->__delegate)) { // write unref ourselfs if we don't have a delegate yet (see cachedJavaPrototype and Java::__factory in __call below) - if(JAVA_DEBUG) {echo "unref java:"; echo $this->__java; echo "\n";} - $client->unref($this->__java); - } - } - } - /** - * Call a method on a Java object - * - * Example: - * - * $s->substring(1, 10); - * - * @param string The method name - * @param array The argument array - */ - function __call($method, $args) { - $client = $this->__client; + // Cancel proxy creation: If the created instance is collected + // before the next java statement is executed, we set the result + // type to void + if($preparedToSendBuffer && + $client->cancelProxyCreationTag==$this->__cancelProxyCreationTag) { - $sig="@{$this->__signature}@$method"; - $len = count($args); - $args2=array($this->__java); - for($i=0; $i<$len; $i++) { - switch(gettype($val = $args[$i])) { - case 'boolean': array_push($args2, $val); $sig.='@b'; break; - case 'integer': array_push($args2, $val); $sig.='@i'; break; - case 'double': array_push($args2, $val); $sig.='@d'; break; - case 'string': array_push($args2, htmlspecialchars($val, ENT_COMPAT,"ISO-8859-1")); $sig.='@s'; break; - case 'array':$sig="~INVALID"; break; - case 'object': - if($val instanceof java_JavaType) { - array_push($args2, $val->__java); - $sig.="@o{$val->__signature}"; - } - else { - $sig="~INVALID"; - } - break; - case 'resource': array_push($args2, $val); $sig.='@r'; break; - case 'NULL': array_push($args2, $val); $sig.='@N'; break; - case 'unknown type': array_push($args2, $val); $sig.='@u'; break; - default: throw new java_IllegalArgumentException($val); - } + $preparedToSendBuffer[6]="3"; + if(JAVA_DEBUG) {echo "cancel result proxy creation:"; echo $this->__java; echo " {$client->preparedToSendBuffer}"; echo "\n";} + $client->sendBuffer.=$preparedToSendBuffer; + $preparedToSendBuffer = null; + $client->asyncCtx -= 1; + } else { + if(!isset($this->__delegate)) { // write unref ourselfs if we don't have a delegate yet (see cachedJavaPrototype and Java::__factory in __call below) + if(JAVA_DEBUG) {echo "unref java:"; echo $this->__java; echo "\n";} + $client->unref($this->__java); + } + } } + /** + * Call a method on a Java object + * + * Example: + * + * $s->substring(1, 10); + * + * @param string The method name + * @param array The argument array + */ + function __call($method, $args) { + $client = $this->__client; - if(array_key_exists($sig, $client->methodCache)) { - if(JAVA_DEBUG) { echo "cache hit for __call: $sig\n"; } - $cacheEntry = &$client->methodCache[$sig]; - $client->sendBuffer.=$client->preparedToSendBuffer; - if(strlen($client->sendBuffer)>=JAVA_SEND_SIZE) { - if($client->protocol->handler->write($client->sendBuffer)<=0) - throw new java_IllegalStateException("Out of sync. Check backend log for details."); - $client->sendBuffer=null; - } - $client->preparedToSendBuffer=vsprintf($cacheEntry->fmt, $args2); - if(JAVA_DEBUG) {print_r($args2); echo "set prepared to send buffer: {$client->preparedToSendBuffer}, {$cacheEntry->fmt}\n";} - if($cacheEntry->resultVoid) { - $client->cancelProxyCreationTag += 1; // expire tag - return null; - } else { - $result = clone($client->cachedJavaPrototype); - $result->__factory = $cacheEntry->factory; - $result->__java = ++$client->asyncCtx; - if(JAVA_DEBUG) {echo "setresult from __call cache: object:"; echo sprintf("%x", $client->asyncCtx); echo "\n";} - $result->__signature = $cacheEntry->signature; - $result->__cancelProxyCreationTag = ++$client->cancelProxyCreationTag; - return $result; - } - } else { - if(JAVA_DEBUG) { echo "cache miss for __call: $sig\n"; } - $client->currentCacheKey = $sig; - $retval = parent::__call($method, $args); - return $retval; + $sig="@{$this->__signature}@$method"; + $len = count($args); + $args2=array($this->__java); + for($i=0; $i<$len; $i++) { + switch(gettype($val = $args[$i])) { + case 'boolean': array_push($args2, $val); $sig.='@b'; break; + case 'integer': array_push($args2, $val); $sig.='@i'; break; + case 'double': array_push($args2, $val); $sig.='@d'; break; + case 'string': array_push($args2, htmlspecialchars($val, ENT_COMPAT,"ISO-8859-1")); $sig.='@s'; break; + case 'array':$sig="~INVALID"; break; + case 'object': + if($val instanceof java_JavaType) { + array_push($args2, $val->__java); + $sig.="@o{$val->__signature}"; + } + else { + $sig="~INVALID"; + } + break; + case 'resource': array_push($args2, $val); $sig.='@r'; break; + case 'NULL': array_push($args2, $val); $sig.='@N'; break; + case 'unknown type': array_push($args2, $val); $sig.='@u'; break; + default: throw new java_IllegalArgumentException($val); + } + } + + if(array_key_exists($sig, $client->methodCache)) { + if(JAVA_DEBUG) { echo "cache hit for __call: $sig\n"; } + $cacheEntry = &$client->methodCache[$sig]; + $client->sendBuffer.=$client->preparedToSendBuffer; + if(strlen($client->sendBuffer)>=JAVA_SEND_SIZE) { + if($client->protocol->handler->write($client->sendBuffer)<=0) + throw new java_IllegalStateException("Out of sync. Check backend log for details."); + $client->sendBuffer=null; + } + $client->preparedToSendBuffer=vsprintf($cacheEntry->fmt, $args2); + if(JAVA_DEBUG) {print_r($args2); echo "set prepared to send buffer: {$client->preparedToSendBuffer}, {$cacheEntry->fmt}\n";} + if($cacheEntry->resultVoid) { + $client->cancelProxyCreationTag += 1; // expire tag + return null; + } else { + $result = clone($client->cachedJavaPrototype); + $result->__factory = $cacheEntry->factory; + $result->__java = ++$client->asyncCtx; + if(JAVA_DEBUG) {echo "setresult from __call cache: object:"; echo sprintf("%x", $client->asyncCtx); echo "\n";} + $result->__signature = $cacheEntry->signature; + $result->__cancelProxyCreationTag = ++$client->cancelProxyCreationTag; + return $result; + } + } else { + if(JAVA_DEBUG) { echo "cache miss for __call: $sig\n"; } + $client->currentCacheKey = $sig; + $retval = parent::__call($method, $args); + return $retval; + } } - } } /** * @access private */ class java_InternalJava extends Java { - function __construct($proxy) { - $this->__delegate = $proxy; - $this->__java = $proxy->__java; - $this->__signature = $proxy->__signature; - $this->__client = $proxy->__client; - } + function __construct($proxy) { + $this->__delegate = $proxy; + $this->__java = $proxy->__java; + $this->__signature = $proxy->__signature; + $this->__client = $proxy->__client; + } } /** * @access private */ class java_class extends Java { - function __construct() { - $this->__client = __javaproxy_Client_getClient(); + function __construct() { + $this->__client = __javaproxy_Client_getClient(); - $args = func_get_args(); - $name = array_shift($args); + $args = func_get_args(); + $name = array_shift($args); - // compatibility with the C implementation - if(is_array($name)) { $args = $name; $name = array_shift($args); } + // compatibility with the C implementation + if(is_array($name)) { $args = $name; $name = array_shift($args); } - /* do not delete this line, it is used when generating Mono.inc from Java.inc */ + /* do not delete this line, it is used when generating Mono.inc from Java.inc */ - $delegate = $this->__delegate = $this->__client->referenceObject($name, $args); + $delegate = $this->__delegate = $this->__client->referenceObject($name, $args); - $this->__java = $delegate->__java; - $this->__signature = $delegate->__signature; - } + $this->__java = $delegate->__java; + $this->__signature = $delegate->__signature; + } } /** * @access private @@ -1096,95 +1096,95 @@ class java_class extends Java { class JavaClass extends java_class{} /** * A decorator pattern which overrides all magic methods. - * + * * @access private */ class java_exception extends Exception implements java_JavaType { - /** @access private */ - public $__serialID, $__java, $__client; - /** @access private */ - public $__delegate; - /** @access private */ - public $__signature; - /** @access private */ - public $__hasDeclaredExceptions; - - /** - * Create a new Exception. - * - * Example: - * - * $ex = new java_exception("java.lang.NullPointerException"); - * throw $ex; - * - */ - function __construct() { - $this->__client = __javaproxy_Client_getClient(); + /** @access private */ + public $__serialID, $__java, $__client; + /** @access private */ + public $__delegate; + /** @access private */ + public $__signature; + /** @access private */ + public $__hasDeclaredExceptions; + + /** + * Create a new Exception. + * + * Example: + * + * $ex = new java_exception("java.lang.NullPointerException"); + * throw $ex; + * + */ + function __construct() { + $this->__client = __javaproxy_Client_getClient(); - $args = func_get_args(); - $name = array_shift($args); + $args = func_get_args(); + $name = array_shift($args); - // compatibility with the C implementation - if(is_array($name)) { $args = $name; $name = array_shift($args); } + // compatibility with the C implementation + if(is_array($name)) { $args = $name; $name = array_shift($args); } - if (count($args) == 0) - Exception::__construct($name); - else - Exception::__construct($args[0]); + if (count($args) == 0) + Exception::__construct($name); + else + Exception::__construct($args[0]); - /* do not delete this line, it is used when generating Mono.inc from Java.inc */ + /* do not delete this line, it is used when generating Mono.inc from Java.inc */ - $delegate = $this->__delegate = $this->__client->createObject($name, $args); + $delegate = $this->__delegate = $this->__client->createObject($name, $args); - $this->__java = $delegate->__java; - $this->__signature = $delegate->__signature; - $this->__hasDeclaredExceptions = 'T'; - } - /** - * @access private - */ - function __cast($type) { - return $this->__delegate->__cast($type); - } - /** - * @access private - */ - function __sleep() { - $this->__delegate->__sleep(); - return array("__delegate"); - } - /** - * @access private - */ - function __wakeup() { - $this->__delegate->__wakeup(); - $this->__java = $this->__delegate->__java; - $this->__client = $this->__delegate->__client; - } - /** - * @access private - */ - function __get($key) { - return $this->__delegate->__get($key); - } - /** - * @access private - */ - function __set($key, $val) { - $this->__delegate->__set($key, $val); - } - /** - * @access private - */ - function __call($method, $args) { - return $this->__delegate->__call($method, $args); - } - /** - * @access private - */ - function __toString() { - return $this->__delegate->__toExceptionString($this->getTraceAsString()); - } + $this->__java = $delegate->__java; + $this->__signature = $delegate->__signature; + $this->__hasDeclaredExceptions = 'T'; + } + /** + * @access private + */ + function __cast($type) { + return $this->__delegate->__cast($type); + } + /** + * @access private + */ + function __sleep() { + $this->__delegate->__sleep(); + return array("__delegate"); + } + /** + * @access private + */ + function __wakeup() { + $this->__delegate->__wakeup(); + $this->__java = $this->__delegate->__java; + $this->__client = $this->__delegate->__client; + } + /** + * @access private + */ + function __get($key) { + return $this->__delegate->__get($key); + } + /** + * @access private + */ + function __set($key, $val) { + $this->__delegate->__set($key, $val); + } + /** + * @access private + */ + function __call($method, $args) { + return $this->__delegate->__call($method, $args); + } + /** + * @access private + */ + function __toString() { + return $this->__delegate->__toExceptionString($this->getTraceAsString()); + } } /** * The java exception proxy. @@ -1194,7 +1194,7 @@ class java_exception extends Exception implements java_JavaType { * $ex = new JavaException("java.lang.NullPointerException"); * throw $ex; *
- * + * * @access public */ class JavaException extends java_exception {} @@ -1203,22 +1203,22 @@ class JavaException extends java_exception {} * @access private */ class java_InternalException extends JavaException { - function __construct($proxy, $exception) { - $this->__delegate = $proxy; - $this->__java = $proxy->__java; - $this->__signature = $proxy->__signature; - $this->__client = $proxy->__client; - $this->__hasDeclaredExceptions = $exception; - } + function __construct($proxy, $exception) { + $this->__delegate = $proxy; + $this->__java = $proxy->__java; + $this->__signature = $proxy->__signature; + $this->__client = $proxy->__client; + $this->__hasDeclaredExceptions = $exception; + } } /** * @access private */ class java_JavaProxyProxy extends Java { - function __construct($client) { - $this->__client = $client; - } + function __construct($client) { + $this->__client = $client; + } } ?> diff --git a/legacy/server/META-INF/java/Protocol.inc b/legacy/server/META-INF/java/Protocol.inc index edbd9b4..f04d5dd 100644 --- a/legacy/server/META-INF/java/Protocol.inc +++ b/legacy/server/META-INF/java/Protocol.inc @@ -1,47 +1,47 @@ RUNTIME["PARSER"]=="NATIVE" - ? (0103-JAVA_PREFER_VALUES) - : (0100+JAVA_PREFER_VALUES); - if(is_int(JAVA_LOG_LEVEL)) { - $compatibility |= 128 | (7 & JAVA_LOG_LEVEL)<<2; - } - $compatibility = chr ($compatibility); - return $compatibility; + static $compatibility = null; + + if ($compatibility) return $compatibility; + + $compatibility = $client->RUNTIME["PARSER"]=="NATIVE" + ? (0103-JAVA_PREFER_VALUES) + : (0100+JAVA_PREFER_VALUES); + if(is_int(JAVA_LOG_LEVEL)) { + $compatibility |= 128 | (7 & JAVA_LOG_LEVEL)<<2; + } + $compatibility = chr ($compatibility); + return $compatibility; } /** @@ -87,66 +87,66 @@ function java_getCompatibilityOption($client) { * @access private */ class java_EmptyChannel { - protected $handler; - private $res; - - function __construct($handler) { - $this->handler = $handler; - } - function shutdownBrokenConnection () {} - function fwrite($data) { - return $this->handler->fwrite($data); - } - function fread($size) { - return $this->handler->fread($size); - } - - function getKeepAliveA() { - return ""; - } - function getKeepAliveE() { - return ""; - } - function getKeepAlive() { - return $this->getKeepAliveE(); - } - - function error() { - trigger_error("An unchecked exception occured during script execution. Please check the server log files for details.", E_USER_ERROR); - } - function checkA($peer) { - $val=$this->res[6]; - if ($val !='A') fclose($peer); - if ($val !='A' && $val !='E') { - $this->error(); - } - } - function checkE() { - $val = $this->res[6]; - if ($val !='E') { - $this->error(); - } - } - /** Used by socket channel (phase 2) */ - function keepAliveS() { - $this->res = $this->fread(10); // - } - /** Used by chunked socket channel (phase 2) */ - function keepAliveSC() { - $this->res = $this->fread(10);// - $this->fwrite(""); // 0\r\n\r\n - $this->fread(JAVA_RECV_SIZE); // read 0\r\n\r\n JAVA_RECV_SIZE is dummy - } - - /** Used by EmptyChannel (phase 1) */ - function keepAliveH() { - $this->res = $this->handler->read(10);// HTTP response - } - - function keepAlive() { - $this->keepAliveH(); - $this->checkE(); - } + protected $handler; + private $res; + + function __construct($handler) { + $this->handler = $handler; + } + function shutdownBrokenConnection () {} + function fwrite($data) { + return $this->handler->fwrite($data); + } + function fread($size) { + return $this->handler->fread($size); + } + + function getKeepAliveA() { + return ""; + } + function getKeepAliveE() { + return ""; + } + function getKeepAlive() { + return $this->getKeepAliveE(); + } + + function error() { + trigger_error("An unchecked exception occured during script execution. Please check the server log files for details.", E_USER_ERROR); + } + function checkA($peer) { + $val=$this->res[6]; + if ($val !='A') fclose($peer); + if ($val !='A' && $val !='E') { + $this->error(); + } + } + function checkE() { + $val = $this->res[6]; + if ($val !='E') { + $this->error(); + } + } + /** Used by socket channel (phase 2) */ + function keepAliveS() { + $this->res = $this->fread(10); // + } + /** Used by chunked socket channel (phase 2) */ + function keepAliveSC() { + $this->res = $this->fread(10);// + $this->fwrite(""); // 0\r\n\r\n + $this->fread(JAVA_RECV_SIZE); // read 0\r\n\r\n JAVA_RECV_SIZE is dummy + } + + /** Used by EmptyChannel (phase 1) */ + function keepAliveH() { + $this->res = $this->handler->read(10);// HTTP response + } + + function keepAlive() { + $this->keepAliveH(); + $this->checkE(); + } } /** @@ -156,21 +156,21 @@ class java_EmptyChannel { * @access private */ abstract class java_SocketChannel extends java_EmptyChannel { - public $peer, $host; - - function __construct($peer, $host) { - $this->peer = $peer; - $this->host = $host; - } - function fwrite($data) { - return fwrite($this->peer, $data); - } - function fread($size) { - return fread($this->peer, $size); - } - function shutdownBrokenConnection () { - fclose($this->peer); - } + public $peer, $host; + + function __construct($peer, $host) { + $this->peer = $peer; + $this->host = $host; + } + function fwrite($data) { + return fwrite($this->peer, $data); + } + function fread($size) { + return fread($this->peer, $size); + } + function shutdownBrokenConnection () { + fclose($this->peer); + } } /** * Persistent version of the above @@ -178,34 +178,34 @@ abstract class java_SocketChannel extends java_EmptyChannel { * @access private */ class java_SocketChannelP extends java_SocketChannel { - function getKeepAlive() {return $this->getKeepAliveA();} - function keepAlive() { $this->keepAliveS(); $this->checkA($this->peer); } + function getKeepAlive() {return $this->getKeepAliveA();} + function keepAlive() { $this->keepAliveS(); $this->checkA($this->peer); } } /** * Chunked version of the socket channel. Used in phase 2. - * + * * @access private */ class java_ChunkedSocketChannel extends java_SocketChannel { - function fwrite($data) { - $len = dechex(strlen($data)); - return fwrite($this->peer, "${len}\r\n${data}\r\n"); - } - function fread($size) { - $length = hexdec(fgets($this->peer, JAVA_RECV_SIZE)); - $data = ""; - while ($length > 0) { - $str = fread($this->peer, $length); - if (feof ($this->peer)) return null; - - $length -= strlen($str); - $data .= $str; - } - fgets($this->peer, 3); // \r\n - return $data; - } - function keepAlive() { $this->keepAliveSC(); $this->checkE(); fclose ($this->peer); } + function fwrite($data) { + $len = dechex(strlen($data)); + return fwrite($this->peer, "${len}\r\n${data}\r\n"); + } + function fread($size) { + $length = hexdec(fgets($this->peer, JAVA_RECV_SIZE)); + $data = ""; + while ($length > 0) { + $str = fread($this->peer, $length); + if (feof ($this->peer)) return null; + + $length -= strlen($str); + $data .= $str; + } + fgets($this->peer, 3); // \r\n + return $data; + } + function keepAlive() { $this->keepAliveSC(); $this->checkE(); fclose ($this->peer); } } /** @@ -216,39 +216,39 @@ class java_ChunkedSocketChannel extends java_SocketChannel { * @access private */ class java_SocketHandler { - public $protocol, $channel; - - function __construct($protocol, $channel) { - $this->protocol = $protocol; - $this->channel = $channel; - } - function write($data) { - return $this->channel->fwrite($data); - } - // fallback for EmptyChannel, phase 1 - function fwrite($data) {return $this->write($data);} - - function read($size) { - return $this->channel->fread($size); - } - // fallback for EmptyChannel, phase 1 - function fread($size) {return $this->read($size);} - - function redirect() {} - function getKeepAlive() { - return $this->channel->getKeepAlive(); - } - function keepAlive() { - $this->channel->keepAlive(); - } - function dieWithBrokenConnection($msg) { - unset($this->protocol->client->protocol); - trigger_error ($msg?$msg:"unknown error: please see back end log for details", E_USER_ERROR); - } - function shutdownBrokenConnection ($msg) { - $this->channel->shutdownBrokenConnection(); - $this->dieWithBrokenConnection($msg); - } + public $protocol, $channel; + + function __construct($protocol, $channel) { + $this->protocol = $protocol; + $this->channel = $channel; + } + function write($data) { + return $this->channel->fwrite($data); + } + // fallback for EmptyChannel, phase 1 + function fwrite($data) {return $this->write($data);} + + function read($size) { + return $this->channel->fread($size); + } + // fallback for EmptyChannel, phase 1 + function fread($size) {return $this->read($size);} + + function redirect() {} + function getKeepAlive() { + return $this->channel->getKeepAlive(); + } + function keepAlive() { + $this->channel->keepAlive(); + } + function dieWithBrokenConnection($msg) { + unset($this->protocol->client->protocol); + trigger_error ($msg?$msg:"unknown error: please see back end log for details", E_USER_ERROR); + } + function shutdownBrokenConnection ($msg) { + $this->channel->shutdownBrokenConnection(); + $this->dieWithBrokenConnection($msg); + } } /** * Used when PHP is running within a servlet environment. @@ -261,131 +261,131 @@ class java_SocketHandler { * @access private */ class java_SimpleHttpHandler extends java_SocketHandler { - public $headers, $cookies; - - public $context, $ssl, $port; // used by reopen - public $host; // used when creating a socket channel lazily. - /** - * Create a SocketChannel which is used to communicate with the SocketContextServer - */ - function createChannel() { - // fast path; used by the JEE or servlet back end to connect to PHP - $channelName = java_getHeader("X_JAVABRIDGE_REDIRECT", $_SERVER); - $context = java_getHeader("X_JAVABRIDGE_CONTEXT", $_SERVER); - $len = strlen($context); - $len0 = java_getCompatibilityOption($this->protocol->client); // short path S1: no PUT request - $len1 = chr($len&0xFF); $len>>=8; - $len2 = chr($len&0xFF); - // simulate phase 1: PUT request to the back end - $this->channel = new java_EmptyChannel($this); - // simulate phase 2 : parse headers and extract comm. channel - $this->channel = $this->getChannel($channelName); - // we know the comm. channel is a socket channel, otherwise this class wouldn't be used - $this->protocol->socketHandler=new java_SocketHandler($this->protocol, $this->channel); - $this->protocol->write("\177${len0}${len1}${len2}${context}"); - $this->context = sprintf("X_JAVABRIDGE_CONTEXT: %s\r\n", $context); - - $this->protocol->handler = $this->protocol->socketHandler; - $this->protocol->handler->write($this->protocol->client->sendBuffer) - or $this->protocol->handler->shutdownBrokenConnection("Broken local connection handle"); - $this->protocol->client->sendBuffer=null; - $this->protocol->handler->read(1) - or $this->protocol->handler->shutdownBrokenConnection("Broken local connection handle"); - } - - function __construct($protocol, $ssl, $host, $port) { - $this->cookies = array(); - $this->protocol = $protocol; - $this->ssl = $ssl; - $this->host = $host; - $this->port = $port; - $this->createChannel(); - } - function getCookies() { - $str=""; - $first=true; - foreach($_COOKIE as $k => $v) { - $str .= ($first ? "Cookie: $k=$v":"; $k=$v"); - $first=false; - } - if(!$first) $str .= "\r\n"; - return $str; - } - function getContextFromCgiEnvironment() { - $ctx = java_getHeader('X_JAVABRIDGE_CONTEXT', $_SERVER); - return $ctx; - } - function getContext() { - static $context = null; - if($context) return $context; - - $ctx = $this->getContextFromCgiEnvironment(); - $context = ""; - if($ctx) { - $context = sprintf("X_JAVABRIDGE_CONTEXT: %s\r\n", $ctx); - } - return $context; - } - function getWebAppInternal() { - // from createHttpHandler - $context = $this->protocol->webContext; - if(isset($context)) return $context; - - /* Coerce a http://xyz.com/kontext/foo.php request to the back - end: http://xyz.com:{java_hosts[0]}/kontext/foo.php. For - example if we receive a request: - http://localhost/sessionSharing.php and java.servlet is On and - java.hosts is "127.0.0.1:8080" the code would connect to the - back end: - http://127.0.0.1:8080/sessionSharing.phpjavabridge. This - creates a cookie with PATH value "/". If java_servlet is User - the request http://localhost/myContext/sessionSharing.php the - code would connect to - http://127.0.0.1/myContext/sessionSharing.phpjavabridge and a - cookie with a PATH value "/myContext" would be created. - */ - return (JAVA_SERVLET == "User" && - array_key_exists('PHP_SELF', $_SERVER) && - array_key_exists('HTTP_HOST', $_SERVER)) - ? $_SERVER['PHP_SELF']."javabridge" - : null; - } - function getWebApp() { - $context = $this->getWebAppInternal(); - if(is_null($context)) $context = JAVA_SERVLET; - if(is_null($context) || $context[0]!="/") - $context = "/JavaBridge/JavaBridge.phpjavabridge"; - return $context; - } - function write($data) { - return $this->protocol->socketHandler->write($data); - } - function doSetCookie($key, $val, $path) { - $path=trim($path); - - $webapp = $this->getWebAppInternal(); if(!$webapp) $path="/"; - setcookie($key, $val, 0, $path); - } - function read($size) { - return $this->protocol->socketHandler->read($size); - } - - function getChannel($channelName) { - $errstr = null; $errno = null; - $peer = pfsockopen($this->host, $channelName, $errno, $errstr, 20); - if (!$peer) throw new java_IllegalStateException("No ContextServer for {$this->host}:{$channelName}. Error: $errstr ($errno)\n"); - stream_set_timeout($peer, -1); - return new java_SocketChannelP($peer, $this->host); - } - function keepAlive() { - parent::keepAlive(); - } - - /** - * Prepare for phase 2: Open a SocketChannel and redirect further - * communication to this channel. - */ - function redirect() {} + public $headers, $cookies; + + public $context, $ssl, $port; // used by reopen + public $host; // used when creating a socket channel lazily. + /** + * Create a SocketChannel which is used to communicate with the SocketContextServer + */ + function createChannel() { + // fast path; used by the JEE or servlet back end to connect to PHP + $channelName = java_getHeader("X_JAVABRIDGE_REDIRECT", $_SERVER); + $context = java_getHeader("X_JAVABRIDGE_CONTEXT", $_SERVER); + $len = strlen($context); + $len0 = java_getCompatibilityOption($this->protocol->client); // short path S1: no PUT request + $len1 = chr($len&0xFF); $len>>=8; + $len2 = chr($len&0xFF); + // simulate phase 1: PUT request to the back end + $this->channel = new java_EmptyChannel($this); + // simulate phase 2 : parse headers and extract comm. channel + $this->channel = $this->getChannel($channelName); + // we know the comm. channel is a socket channel, otherwise this class wouldn't be used + $this->protocol->socketHandler=new java_SocketHandler($this->protocol, $this->channel); + $this->protocol->write("\177${len0}${len1}${len2}${context}"); + $this->context = sprintf("X_JAVABRIDGE_CONTEXT: %s\r\n", $context); + + $this->protocol->handler = $this->protocol->socketHandler; + $this->protocol->handler->write($this->protocol->client->sendBuffer) + or $this->protocol->handler->shutdownBrokenConnection("Broken local connection handle"); + $this->protocol->client->sendBuffer=null; + $this->protocol->handler->read(1) + or $this->protocol->handler->shutdownBrokenConnection("Broken local connection handle"); + } + + function __construct($protocol, $ssl, $host, $port) { + $this->cookies = array(); + $this->protocol = $protocol; + $this->ssl = $ssl; + $this->host = $host; + $this->port = $port; + $this->createChannel(); + } + function getCookies() { + $str=""; + $first=true; + foreach($_COOKIE as $k => $v) { + $str .= ($first ? "Cookie: $k=$v":"; $k=$v"); + $first=false; + } + if(!$first) $str .= "\r\n"; + return $str; + } + function getContextFromCgiEnvironment() { + $ctx = java_getHeader('X_JAVABRIDGE_CONTEXT', $_SERVER); + return $ctx; + } + function getContext() { + static $context = null; + if($context) return $context; + + $ctx = $this->getContextFromCgiEnvironment(); + $context = ""; + if($ctx) { + $context = sprintf("X_JAVABRIDGE_CONTEXT: %s\r\n", $ctx); + } + return $context; + } + function getWebAppInternal() { + // from createHttpHandler + $context = $this->protocol->webContext; + if(isset($context)) return $context; + + /* Coerce a http://xyz.com/kontext/foo.php request to the back + end: http://xyz.com:{java_hosts[0]}/kontext/foo.php. For + example if we receive a request: + http://localhost/sessionSharing.php and java.servlet is On and + java.hosts is "127.0.0.1:8080" the code would connect to the + back end: + http://127.0.0.1:8080/sessionSharing.phpjavabridge. This + creates a cookie with PATH value "/". If java_servlet is User + the request http://localhost/myContext/sessionSharing.php the + code would connect to + http://127.0.0.1/myContext/sessionSharing.phpjavabridge and a + cookie with a PATH value "/myContext" would be created. + */ + return (JAVA_SERVLET == "User" && + array_key_exists('PHP_SELF', $_SERVER) && + array_key_exists('HTTP_HOST', $_SERVER)) + ? $_SERVER['PHP_SELF']."javabridge" + : null; + } + function getWebApp() { + $context = $this->getWebAppInternal(); + if(is_null($context)) $context = JAVA_SERVLET; + if(is_null($context) || $context[0]!="/") + $context = "/JavaBridge/JavaBridge.phpjavabridge"; + return $context; + } + function write($data) { + return $this->protocol->socketHandler->write($data); + } + function doSetCookie($key, $val, $path) { + $path=trim($path); + + $webapp = $this->getWebAppInternal(); if(!$webapp) $path="/"; + setcookie($key, $val, 0, $path); + } + function read($size) { + return $this->protocol->socketHandler->read($size); + } + + function getChannel($channelName) { + $errstr = null; $errno = null; + $peer = pfsockopen($this->host, $channelName, $errno, $errstr, 20); + if (!$peer) throw new java_IllegalStateException("No ContextServer for {$this->host}:{$channelName}. Error: $errstr ($errno)\n"); + stream_set_timeout($peer, -1); + return new java_SocketChannelP($peer, $this->host); + } + function keepAlive() { + parent::keepAlive(); + } + + /** + * Prepare for phase 2: Open a SocketChannel and redirect further + * communication to this channel. + */ + function redirect() {} } /** @@ -396,185 +396,185 @@ class java_SimpleHttpHandler extends java_SocketHandler { * @access private */ class java_SimpleHttpTunnelHandler extends java_SimpleHttpHandler { - // the initial socket connection, may redirect to - // a socket connection later on - public $socket; - protected $hasContentLength = false; - - function createSimpleChannel () { - $this->channel = new java_EmptyChannel($this); - } - function createChannel() { - $this->createSimpleChannel(); - } - function shutdownBrokenConnection ($msg) { - fclose($this->socket); - $this->dieWithBrokenConnection($msg); - } - function checkSocket($socket, &$errno, &$errstr) { - if (!$socket) { - $msg="Could not connect to the JEE server {$this->ssl}{$this->host}:{$this->port}. Please start it."; - $msg.=java_checkCliSapi() - ?" Or define('JAVA_HOSTS', 9267); define('JAVA_SERVLET', false); before including 'Java.inc' and try again. Error message: $errstr ($errno)\n" - :" Error message: $errstr ($errno)\n"; - throw new java_ConnectException($msg); - } - } - function open() { - $errno = null; $errstr = null; - $socket = fsockopen("{$this->ssl}{$this->host}", $this->port, $errno, $errstr, 20); - $this->checkSocket($socket, $errno, $errstr); - - stream_set_timeout($socket, -1); - $this->socket = $socket; - } - // fallback for EmptyChannel, phase 1 - function fread($size) { - $length = hexdec(fgets($this->socket, JAVA_RECV_SIZE)); - $data = ""; - while ($length > 0) { - $str = fread($this->socket, $length); - if (feof ($this->socket)) return null; - - $length -= strlen($str); - $data .= $str; - } - fgets($this->socket, 3); //\r\n - return $data; - } - // fallback for EmptyChannel, phase 1 - function fwrite($data) { - $len = dechex(strlen($data)); - return fwrite($this->socket, "${len}\r\n${data}\r\n"); - } - function close() { - fwrite($this->socket, "0\r\n\r\n"); - fgets($this->socket, JAVA_RECV_SIZE); // 0\r\n - fgets($this->socket, 3); // \r\n - fclose($this->socket); - } - function __construct($protocol, $ssl, $host, $port) { - parent::__construct($protocol, $ssl, $host, $port); - $this->open(); - } - function read($size) { - if(is_null($this->headers)) $this->parseHeaders(); - if (isset($this->headers["http_error"])) { - if (isset($this->headers["transfer_chunked"])) { - $str = $this->fread(JAVA_RECV_SIZE); - } elseif (isset($this->headers['content_length'])) { - $len = $this->headers['content_length']; - for($str=fread($this->socket, $len); strlen($str)<$len; $str.=fread($this->socket,$len-strlen($str))) - if (feof ($this->socket)) break; - } else { - $str=fread($this->socket, JAVA_RECV_SIZE); - } - $this->shutdownBrokenConnection($str); - } - return $this->fread(JAVA_RECV_SIZE); - } - function getBodyFor ($compat, $data) { - $len = dechex(2+strlen($data)); - return "Cache-Control: no-cache\r\nPragma: no-cache\r\nTransfer-Encoding: chunked\r\n\r\n${len}\r\n\177${compat}${data}\r\n"; - } - function write($data) { - $compat = java_getCompatibilityOption($this->protocol->client); - $this->headers = null; - $socket = $this->socket; - $webapp = $this->getWebApp(); - $cookies = $this->getCookies(); - $context = $this->getContext(); - $res = "PUT "; - $res .= $webapp; - $res .= " HTTP/1.1\r\n"; - $res .= "Host: {$this->host}:{$this->port}\r\n"; - $res .= $context; - $res .= $cookies; - $res .= $this->getBodyFor($compat, $data); - - $count = fwrite($socket, $res) or $this->shutdownBrokenConnection("Broken connection handle"); - fflush($socket) or $this->shutdownBrokenConnection("Broken connection handle"); - - return $count; - } - - function parseHeaders() { - $this->headers = array(); - $line = trim(fgets($this->socket, JAVA_RECV_SIZE)); - $ar = explode (" ", $line); - - $code = ((int)$ar[1]); - if ($code != 200) $this->headers["http_error"] = $code; - - while (($str = trim(fgets($this->socket, JAVA_RECV_SIZE)))) { - if($str[0]=='X') { - if(!strncasecmp("X_JAVABRIDGE_REDIRECT", $str, 21)) { - $this->headers["redirect"]=trim(substr($str, 22)); - } else if(!strncasecmp("X_JAVABRIDGE_CONTEXT", $str, 20)) { - $this->headers["context"]=trim(substr($str, 21)); - } - } else if($str[0]=='S') { // Set-Cookie: - if(!strncasecmp("SET-COOKIE", $str, 10)) { - $str=substr($str, 12); - $this->cookies[]=$str; - - $ar = explode(";", $str); - $cookie = explode("=",$ar[0]); - $path = ""; - if(isset($ar[1])) $p=explode("=", $ar[1]); - if(isset($p)) $path=$p[1]; - $this->doSetCookie($cookie[0], $cookie[1], $path); - } - } else if($str[0]=='C') { // Content-Length - if(!strncasecmp("CONTENT-LENGTH", $str, 14)) { - $this->headers["content_length"]=trim(substr($str, 15)); - $this->hasContentLength = true; - } else if(!strncasecmp("CONNECTION", $str, 10) && !strncasecmp("close", trim(substr($str, 11)), 5)) { - $this->headers["connection_close"] = true; - } - } else if($str[0]=='T') { // Transfer-Encoding - if(!strncasecmp("TRANSFER-ENCODING", $str, 17) && !strncasecmp("chunked", trim(substr($str, 18)), 7)) { - $this->headers["transfer_chunked"] = true; - } - } - } - } - function getSimpleChannel() { - return new java_ChunkedSocketChannel($this->socket, $this->protocol, $this->host); - } - - function redirect() { - $this->isRedirect = isset($this->headers["redirect"]); - if ($this->isRedirect) - $channelName = $this->headers["redirect"]; - - $context = $this->headers["context"]; - $len = strlen($context); - $len0 = chr(0xFF); - $len1 = chr($len&0xFF); $len>>=8; - $len2 = chr($len&0xFF); - if ($this->isRedirect) { // slow path; used by JavaBridgeRunner back end - /* SocketContextServer: redirect to ContextRunner */ - $this->protocol->socketHandler=new java_SocketHandler($this->protocol, $this->getChannel($channelName)); - $this->protocol->write("\177${len0}${len1}${len2}${context}"); - $this->context = sprintf("X_JAVABRIDGE_CONTEXT: %s\r\n", $context); - - $this->close (); - - $this->protocol->handler = $this->protocol->socketHandler; - // short path for $this->protocol->flush(): avoid ContextRunner wait timeout - $this->protocol->handler->write($this->protocol->client->sendBuffer) - or $this->protocol->handler->shutdownBrokenConnection("Broken local connection handle"); - $this->protocol->client->sendBuffer=null; - - // dummy: avoid ack delay - $this->protocol->handler->read(1) - or $this->protocol->handler->shutdownBrokenConnection("Broken local connection handle"); - } else { // fast path; used by JEE or servlet engine - /* No SocketContextServer: keep using the current HTTP connection */ - $this->protocol->handler = $this->protocol->socketHandler=new java_SocketHandler($this->protocol, $this->getSimpleChannel()); - } - } + // the initial socket connection, may redirect to + // a socket connection later on + public $socket; + protected $hasContentLength = false; + + function createSimpleChannel () { + $this->channel = new java_EmptyChannel($this); + } + function createChannel() { + $this->createSimpleChannel(); + } + function shutdownBrokenConnection ($msg) { + fclose($this->socket); + $this->dieWithBrokenConnection($msg); + } + function checkSocket($socket, &$errno, &$errstr) { + if (!$socket) { + $msg="Could not connect to the JEE server {$this->ssl}{$this->host}:{$this->port}. Please start it."; + $msg.=java_checkCliSapi() + ?" Or define('JAVA_HOSTS', 9267); define('JAVA_SERVLET', false); before including 'Java.inc' and try again. Error message: $errstr ($errno)\n" + :" Error message: $errstr ($errno)\n"; + throw new java_ConnectException($msg); + } + } + function open() { + $errno = null; $errstr = null; + $socket = fsockopen("{$this->ssl}{$this->host}", $this->port, $errno, $errstr, 20); + $this->checkSocket($socket, $errno, $errstr); + + stream_set_timeout($socket, -1); + $this->socket = $socket; + } + // fallback for EmptyChannel, phase 1 + function fread($size) { + $length = hexdec(fgets($this->socket, JAVA_RECV_SIZE)); + $data = ""; + while ($length > 0) { + $str = fread($this->socket, $length); + if (feof ($this->socket)) return null; + + $length -= strlen($str); + $data .= $str; + } + fgets($this->socket, 3); //\r\n + return $data; + } + // fallback for EmptyChannel, phase 1 + function fwrite($data) { + $len = dechex(strlen($data)); + return fwrite($this->socket, "${len}\r\n${data}\r\n"); + } + function close() { + fwrite($this->socket, "0\r\n\r\n"); + fgets($this->socket, JAVA_RECV_SIZE); // 0\r\n + fgets($this->socket, 3); // \r\n + fclose($this->socket); + } + function __construct($protocol, $ssl, $host, $port) { + parent::__construct($protocol, $ssl, $host, $port); + $this->open(); + } + function read($size) { + if(is_null($this->headers)) $this->parseHeaders(); + if (isset($this->headers["http_error"])) { + if (isset($this->headers["transfer_chunked"])) { + $str = $this->fread(JAVA_RECV_SIZE); + } elseif (isset($this->headers['content_length'])) { + $len = $this->headers['content_length']; + for($str=fread($this->socket, $len); strlen($str)<$len; $str.=fread($this->socket,$len-strlen($str))) + if (feof ($this->socket)) break; + } else { + $str=fread($this->socket, JAVA_RECV_SIZE); + } + $this->shutdownBrokenConnection($str); + } + return $this->fread(JAVA_RECV_SIZE); + } + function getBodyFor ($compat, $data) { + $len = dechex(2+strlen($data)); + return "Cache-Control: no-cache\r\nPragma: no-cache\r\nTransfer-Encoding: chunked\r\n\r\n${len}\r\n\177${compat}${data}\r\n"; + } + function write($data) { + $compat = java_getCompatibilityOption($this->protocol->client); + $this->headers = null; + $socket = $this->socket; + $webapp = $this->getWebApp(); + $cookies = $this->getCookies(); + $context = $this->getContext(); + $res = "PUT "; + $res .= $webapp; + $res .= " HTTP/1.1\r\n"; + $res .= "Host: {$this->host}:{$this->port}\r\n"; + $res .= $context; + $res .= $cookies; + $res .= $this->getBodyFor($compat, $data); + + $count = fwrite($socket, $res) or $this->shutdownBrokenConnection("Broken connection handle"); + fflush($socket) or $this->shutdownBrokenConnection("Broken connection handle"); + + return $count; + } + + function parseHeaders() { + $this->headers = array(); + $line = trim(fgets($this->socket, JAVA_RECV_SIZE)); + $ar = explode (" ", $line); + + $code = ((int)$ar[1]); + if ($code != 200) $this->headers["http_error"] = $code; + + while (($str = trim(fgets($this->socket, JAVA_RECV_SIZE)))) { + if($str[0]=='X') { + if(!strncasecmp("X_JAVABRIDGE_REDIRECT", $str, 21)) { + $this->headers["redirect"]=trim(substr($str, 22)); + } else if(!strncasecmp("X_JAVABRIDGE_CONTEXT", $str, 20)) { + $this->headers["context"]=trim(substr($str, 21)); + } + } else if($str[0]=='S') { // Set-Cookie: + if(!strncasecmp("SET-COOKIE", $str, 10)) { + $str=substr($str, 12); + $this->cookies[]=$str; + + $ar = explode(";", $str); + $cookie = explode("=",$ar[0]); + $path = ""; + if(isset($ar[1])) $p=explode("=", $ar[1]); + if(isset($p)) $path=$p[1]; + $this->doSetCookie($cookie[0], $cookie[1], $path); + } + } else if($str[0]=='C') { // Content-Length + if(!strncasecmp("CONTENT-LENGTH", $str, 14)) { + $this->headers["content_length"]=trim(substr($str, 15)); + $this->hasContentLength = true; + } else if(!strncasecmp("CONNECTION", $str, 10) && !strncasecmp("close", trim(substr($str, 11)), 5)) { + $this->headers["connection_close"] = true; + } + } else if($str[0]=='T') { // Transfer-Encoding + if(!strncasecmp("TRANSFER-ENCODING", $str, 17) && !strncasecmp("chunked", trim(substr($str, 18)), 7)) { + $this->headers["transfer_chunked"] = true; + } + } + } + } + function getSimpleChannel() { + return new java_ChunkedSocketChannel($this->socket, $this->protocol, $this->host); + } + + function redirect() { + $this->isRedirect = isset($this->headers["redirect"]); + if ($this->isRedirect) + $channelName = $this->headers["redirect"]; + + $context = $this->headers["context"]; + $len = strlen($context); + $len0 = chr(0xFF); + $len1 = chr($len&0xFF); $len>>=8; + $len2 = chr($len&0xFF); + if ($this->isRedirect) { // slow path; used by JavaBridgeRunner back end + /* SocketContextServer: redirect to ContextRunner */ + $this->protocol->socketHandler=new java_SocketHandler($this->protocol, $this->getChannel($channelName)); + $this->protocol->write("\177${len0}${len1}${len2}${context}"); + $this->context = sprintf("X_JAVABRIDGE_CONTEXT: %s\r\n", $context); + + $this->close (); + + $this->protocol->handler = $this->protocol->socketHandler; + // short path for $this->protocol->flush(): avoid ContextRunner wait timeout + $this->protocol->handler->write($this->protocol->client->sendBuffer) + or $this->protocol->handler->shutdownBrokenConnection("Broken local connection handle"); + $this->protocol->client->sendBuffer=null; + + // dummy: avoid ack delay + $this->protocol->handler->read(1) + or $this->protocol->handler->shutdownBrokenConnection("Broken local connection handle"); + } else { // fast path; used by JEE or servlet engine + /* No SocketContextServer: keep using the current HTTP connection */ + $this->protocol->handler = $this->protocol->socketHandler=new java_SocketHandler($this->protocol, $this->getSimpleChannel()); + } + } } /** * Used when PHP connects to a servlet environment using a PUT request. @@ -584,335 +584,339 @@ class java_SimpleHttpTunnelHandler extends java_SimpleHttpHandler { * @access private */ class java_HttpTunnelHandler extends java_SimpleHttpTunnelHandler { - // fallback for EmptyChannel, phase 1 - function fread($size) { - if ($this->hasContentLength) - return fread($this->socket, $this->headers["content_length"]); - else - return parent::fread($size); - } - // fallback for EmptyChannel, phase 1 - function fwrite($data) { - if ($this->hasContentLength) - return fwrite($this->socket, $data); - else - return parent::fwrite($data); - } - function close() { - if ($this->hasContentLength) { - fwrite($this->socket, "0\r\n\r\n"); - fclose($this->socket); - } else { - parent::fclose($this->socket); - } - } + // fallback for EmptyChannel, phase 1 + function fread($size) { + if ($this->hasContentLength) + return fread($this->socket, $this->headers["content_length"]); + else + return parent::fread($size); + } + // fallback for EmptyChannel, phase 1 + function fwrite($data) { + if ($this->hasContentLength) + return fwrite($this->socket, $data); + else + return parent::fwrite($data); + } + function close() { + if ($this->hasContentLength) { + fwrite($this->socket, "0\r\n\r\n"); + fclose($this->socket); + } else { + parent::fclose($this->socket); + } + } } /** * @access private */ class java_Protocol { - public $client; - public $webContext; - public $serverName; - - function getOverrideHosts() { - if(array_key_exists('X_JAVABRIDGE_OVERRIDE_HOSTS', $_ENV)) { - $override = $_ENV['X_JAVABRIDGE_OVERRIDE_HOSTS']; - if(!is_null($override) && $override!='/') return $override; - } - // fcgi: override for redirect - return - java_getHeader('X_JAVABRIDGE_OVERRIDE_HOSTS_REDIRECT', $_SERVER); - } - static function getHost() { - static $host = null; - if(is_null($host)) { - $hosts = explode(";", JAVA_HOSTS); - $host = explode(":", $hosts[0]); // TODO: check host list - - // backward compatibility; changed from host:port to [ssl:]host:port - while(count ($host) < 3) array_unshift($host, ""); - if (substr($host[1], 0, 2) == "//") $host[1] = substr($host[1], 2); - } - return $host; - } - function createHttpHandler() { - $overrideHosts = $this->getOverrideHosts(); - $ssl = ""; - if($overrideHosts) { - // handle "s:127.0.0.1:8080//JavaBridge/test.phpjavabridge" - // or "s:127.0.0.1:8080" - // or "/" - // or "" - $s=$overrideHosts; - if((strlen($s)>2) && ($s[1]==':')) { - if($s[0]=='s') - $ssl="ssl://"; - $s = substr($s, 2); - } - $webCtx = strpos($s, "//"); - if($webCtx) - $host = substr($s, 0, $webCtx); - else - $host = $s; - - $idx = strpos($host, ':'); - if($idx) { - if($webCtx) - $port = substr($host, $idx+1, $webCtx); - else - $port = substr($host, $idx+1); - $host = substr($host, 0, $idx); - } else { - $port = "8080"; - } - - if($webCtx) $webCtx = substr($s, $webCtx+1); - $this->webContext = $webCtx; - } else { - $hostVec = java_Protocol::getHost(); - if ($ssl = $hostVec[0]) $ssl .= "://"; - $host = $hostVec[1]; - $port = $hostVec[2]; - } - - $this->serverName = "${ssl}${host}:$port"; - - // short path S1: no PUT request - if ((array_key_exists("X_JAVABRIDGE_REDIRECT", $_SERVER)) || - (array_key_exists("HTTP_X_JAVABRIDGE_REDIRECT", $_SERVER))) - return new java_SimpleHttpHandler($this, $ssl, $host, $port); - - return new java_HttpTunnelHandler($this, $ssl, $host, $port); - } - /** - * connect to a local channel (no servlet engine or app server) - */ - function createSimpleHandler($name, $again=true) { - $channelName = $name; - $errno = null; $errstr = null; - if(is_numeric($channelName)) { - $peer = @pfsockopen($host="127.0.0.1", $channelName, $errno, $errstr, 5); - } else { - $type = $channelName[0]; - list($host, $channelName) = explode(":", $channelName); - $peer = pfsockopen($host, $channelName, $errno, $errstr, 20); - if (!$peer) - throw new java_ConnectException("No Java server at $host:$channelName. Error message: $errstr ($errno)"); - } - if (!$peer) { - - $java=file_exists(ini_get("extension_dir")."/JavaBridge.jar")?ini_get("extension_dir")."/JavaBridge.jar":(java_get_base()."/JavaBridge.jar"); - if (!file_exists($java)) - throw new java_IOException("Could not find $java in ".getcwd().". Download it from http://sf.net/projects/php-java-bridge/files/Binary%20package/php-java-bridge_".JAVA_PEAR_VERSION."/exploded/JavaBridge.jar/download and try again."); - $java_cmd = "java -Dphp.java.bridge.daemon=true -jar \"${java}\" INET_LOCAL:$channelName 0"; - - if (!$again) - throw new java_ConnectException("No Java back end! Please run it with: $java_cmd. Error message: $errstr ($errno)"); - - if (!java_checkCliSapi()) - trigger_error("This PHP SAPI requires a JEE or SERVLET back end. Start it, define ('JAVA_SERVLET', true); define('JAVA_HOSTS', ...); and try again.", E_USER_ERROR); - - system ($java_cmd); - - return $this->createSimpleHandler($name, false); - } - stream_set_timeout($peer, -1); - $handler = new java_SocketHandler($this, new java_SocketChannelP($peer, $host)); - - $compatibility = java_getCompatibilityOption($this->client); - $this->write("\177$compatibility"); - $this->serverName = "127.0.0.1:$channelName"; - return $handler; - } - function java_get_simple_channel() { - return (JAVA_HOSTS&&(!JAVA_SERVLET||(JAVA_SERVLET=="Off"))) ? JAVA_HOSTS : null; - } - function createHandler() { - if(!java_getHeader('X_JAVABRIDGE_OVERRIDE_HOSTS', $_SERVER)&& - ((function_exists("java_get_default_channel")&&($defaultChannel=java_get_default_channel())) || - ($defaultChannel=$this->java_get_simple_channel())) ) { - // if bind.c has started a local back end from Apache/IIS - return $this->createSimpleHandler($defaultChannel); - } else { - return $this->createHttpHandler(); - } - } - function __construct ($client) { - $this->client = $client; - $this->handler = $this->createHandler(); - } - - function redirect() { - $this->handler->redirect(); - } - - function read($size) { - return $this->handler->read($size); - } - - function sendData() { - $this->handler->write($this->client->sendBuffer); - $this->client->sendBuffer=null; - } - function flush() { - if(JAVA_DEBUG) {echo "sending::: "; echo $this->client->sendBuffer; echo "\n";} - $this->sendData(); - } - function getKeepAlive() { - return $this->handler->getKeepAlive(); - } - function keepAlive() { - $this->handler->keepAlive(); - } - function handle() { - $this->client->handleRequests(); - } - function write($data) { - $this->client->sendBuffer.=$data; - } - function finish() { - $this->flush(); - $this->handle(); - $this->redirect(); - } - - function referenceBegin($name) { - $this->client->sendBuffer.=$this->client->preparedToSendBuffer; - if(JAVA_DEBUG) {echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";} - $this->client->preparedToSendBuffer=null; - - $signature=sprintf("", $name); - $this->write($signature); - $signature[6]="2"; - $this->client->currentArgumentsFormat = $signature; - } - function referenceEnd() { - $this->client->currentArgumentsFormat.=$format=""; - $this->write($format); - $this->finish(); - $this->client->currentCacheKey=null; - } - function createObjectBegin($name) { - $this->client->sendBuffer.=$this->client->preparedToSendBuffer; - if(JAVA_DEBUG) {echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";} - $this->client->preparedToSendBuffer=null; - - $signature=sprintf("", $name); - $this->write($signature); - $signature[6]="2"; - $this->client->currentArgumentsFormat = $signature; - } - function createObjectEnd() { - $this->client->currentArgumentsFormat.=$format=""; - $this->write($format); - $this->finish(); - $this->client->currentCacheKey=null; - } - function propertyAccessBegin($object, $method) { - $this->client->sendBuffer.=$this->client->preparedToSendBuffer; - if(JAVA_DEBUG) {echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";} - $this->client->preparedToSendBuffer=null; - - $this->write(sprintf("", $object, $method)); - $this->client->currentArgumentsFormat=""; - } - function propertyAccessEnd() { - $this->client->currentArgumentsFormat.=$format=""; - $this->write($format); - $this->finish(); - $this->client->currentCacheKey=null; - } - function invokeBegin($object, $method) { - $this->client->sendBuffer.=$this->client->preparedToSendBuffer; - if(JAVA_DEBUG) {echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";} - $this->client->preparedToSendBuffer=null; - - $this->write(sprintf("", $object, $method)); - $this->client->currentArgumentsFormat=""; - } - function invokeEnd() { - $this->client->currentArgumentsFormat.=$format=""; - $this->write($format); - $this->finish(); - $this->client->currentCacheKey=null; - } - function resultBegin() { - $this->client->sendBuffer.=$this->client->preparedToSendBuffer; - if(JAVA_DEBUG) {echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";} - $this->client->preparedToSendBuffer=null; - - $this->write(""); - } - function resultEnd() { - $this->client->currentCacheKey=null; - $this->write(""); - $this->flush(); - } - function writeString($name) { - $this->client->currentArgumentsFormat.=$format=""; - $this->write(sprintf($format, htmlspecialchars($name, ENT_COMPAT,"ISO-8859-1"))); - - } - function writeBoolean($boolean) { - $this->client->currentArgumentsFormat.=$format=""; - $this->write(sprintf($format, $boolean)); - } - function writeLong($l) { - $this->client->currentArgumentsFormat.=""; - if($l<0) { - $this->write(sprintf("",-$l)); - } else { - $this->write(sprintf("",$l)); - } - } - function writeULong($l) { - $this->client->currentArgumentsFormat.=$format=""; - $this->write(sprintf($format,$l)); - } - function writeDouble($d) { - $this->client->currentArgumentsFormat.=$format=""; - $this->write(sprintf($format, $d)); - } - function writeObject($object) { - $this->client->currentArgumentsFormat.=$format=""; - $this->write(sprintf($format, $object)); - } - - /* the following routines are not cached */ - function writeException($object, $str) { - $this->write(sprintf("",$object, htmlspecialchars($str, ENT_COMPAT,"ISO-8859-1"))); - } - function writeCompositeBegin_a() { - $this->write(""); - } - function writeCompositeBegin_h() { - $this->write(""); - } - function writeCompositeEnd() { - $this->write(""); - } - function writePairBegin_s($key) { - $this->write(sprintf("

", htmlspecialchars($key, ENT_COMPAT,"ISO-8859-1"))); - } - function writePairBegin_n($key) { - $this->write(sprintf("

",$key)); - } - function writePairBegin() { - $this->write("

"); - } - function writePairEnd() { - $this->write("

"); - } - function writeUnref($object) { - $this->client->sendBuffer.=$this->client->preparedToSendBuffer; - //echo "clear prepared to send buffer\n"; - $this->client->preparedToSendBuffer=null; - $this->write(sprintf("", $object)); - } - - function getServerName() { - return $this->serverName; - } + public $client; + public $webContext; + public $serverName; + + function getOverrideHosts() { + if(array_key_exists('X_JAVABRIDGE_OVERRIDE_HOSTS', $_ENV)) { + $override = $_ENV['X_JAVABRIDGE_OVERRIDE_HOSTS']; + if(!is_null($override) && $override!='/') return $override; + } + // fcgi: override for redirect + return + java_getHeader('X_JAVABRIDGE_OVERRIDE_HOSTS_REDIRECT', $_SERVER); + } + static function getHost() { + static $host = null; + if(is_null($host)) { + $hosts = explode(";", JAVA_HOSTS); + $host = explode(":", $hosts[0]); // TODO: check host list + + // backward compatibility; changed from host:port to [ssl:]host:port + while(count ($host) < 3) array_unshift($host, ""); + if (substr($host[1], 0, 2) == "//") $host[1] = substr($host[1], 2); + } + return $host; + } + function createHttpHandler() { + $overrideHosts = $this->getOverrideHosts(); + $ssl = ""; + if($overrideHosts) { + // handle "s:127.0.0.1:8080//JavaBridge/test.phpjavabridge" + // or "s:127.0.0.1:8080" + // or "/" + // or "" + $s=$overrideHosts; + if((strlen($s)>2) && ($s[1]==':')) { + if($s[0]=='s') + $ssl="ssl://"; + $s = substr($s, 2); + } + $webCtx = strpos($s, "//"); + if($webCtx) + $host = substr($s, 0, $webCtx); + else + $host = $s; + + $idx = strpos($host, ':'); + if($idx) { + if($webCtx) + $port = substr($host, $idx+1, $webCtx); + else + $port = substr($host, $idx+1); + $host = substr($host, 0, $idx); + } else { + $port = "8080"; + } + + if($webCtx) $webCtx = substr($s, $webCtx+1); + $this->webContext = $webCtx; + } else { + $hostVec = java_Protocol::getHost(); + if ($ssl = $hostVec[0]) $ssl .= "://"; + $host = $hostVec[1]; + $port = $hostVec[2]; + } + + $this->serverName = "${ssl}${host}:$port"; + + // short path S1: no PUT request + if ((array_key_exists("X_JAVABRIDGE_REDIRECT", $_SERVER)) || + (array_key_exists("HTTP_X_JAVABRIDGE_REDIRECT", $_SERVER))) + return new java_SimpleHttpHandler($this, $ssl, $host, $port); + + return new java_HttpTunnelHandler($this, $ssl, $host, $port); + } + /** + * connect to a local channel (no servlet engine or app server) + */ + function createSimpleHandler($name, $again=true) { + $channelName = $name; + $errno = null; $errstr = null; + if(is_numeric($channelName)) { + $peer = @pfsockopen($host="127.0.0.1", $channelName, $errno, $errstr, 5); + } else { + $type = $channelName[0]; + list($host, $channelName) = explode(":", $channelName); + $peer = pfsockopen($host, $channelName, $errno, $errstr, 20); + if (!$peer) + throw new java_ConnectException("No Java server at $host:$channelName. Error message: $errstr ($errno)"); + } + if (!$peer) { + + $java=file_exists(ini_get("extension_dir")."/JavaBridge.jar")?ini_get("extension_dir")."/JavaBridge.jar":(java_get_base()."/JavaBridge.jar"); + if (!file_exists($java)) + throw new java_IOException("Could not find $java in ".getcwd().". Download it from http://sf.net/projects/php-java-bridge/files/Binary%20package/php-java-bridge_".JAVA_PEAR_VERSION."/exploded/JavaBridge.jar/download and try again."); + $java_cmd = "java -Dphp.java.bridge.daemon=true -jar \"${java}\" INET_LOCAL:$channelName 0"; + + if (!$again) + throw new java_ConnectException("No Java back end! Please run it with: $java_cmd. Error message: $errstr ($errno)"); + + if (!java_checkCliSapi()) + trigger_error("This PHP SAPI requires a JEE or SERVLET back end. Start it, define ('JAVA_SERVLET', true); define('JAVA_HOSTS', ...); and try again.", E_USER_ERROR); + + system ($java_cmd); + + return $this->createSimpleHandler($name, false); + } + stream_set_timeout($peer, -1); + $handler = new java_SocketHandler($this, new java_SocketChannelP($peer, $host)); + + $compatibility = java_getCompatibilityOption($this->client); + $this->write("\177$compatibility"); + $this->serverName = "127.0.0.1:$channelName"; + return $handler; + } + function java_get_simple_channel() { + return (JAVA_HOSTS&&(!JAVA_SERVLET||(JAVA_SERVLET=="Off"))) ? JAVA_HOSTS : null; + } + function createHandler() { + if(!java_getHeader('X_JAVABRIDGE_OVERRIDE_HOSTS', $_SERVER)&& + ((function_exists("java_get_default_channel")&&($defaultChannel=java_get_default_channel())) || + ($defaultChannel=$this->java_get_simple_channel())) ) { + // if bind.c has started a local back end from Apache/IIS + return $this->createSimpleHandler($defaultChannel); + } else { + return $this->createHttpHandler(); + } + } + function __construct ($client) { + $this->client = $client; + $this->handler = $this->createHandler(); + } + + function redirect() { + $this->handler->redirect(); + } + + function read($size) { + return $this->handler->read($size); + } + + function sendData() { + $this->handler->write($this->client->sendBuffer); + $this->client->sendBuffer=null; + } + function flush() { + if(JAVA_DEBUG) {echo "sending::: "; echo $this->client->sendBuffer; echo "\n";} + $this->sendData(); + } + function getKeepAlive() { + return $this->handler->getKeepAlive(); + } + function keepAlive() { + $this->handler->keepAlive(); + } + function handle() { + $this->client->handleRequests(); + } + function write($data) { + $this->client->sendBuffer.=$data; + } + function finish() { + $this->flush(); + $this->handle(); + $this->redirect(); + } + + function referenceBegin($name) { + $this->client->sendBuffer.=$this->client->preparedToSendBuffer; + if(JAVA_DEBUG) {echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";} + $this->client->preparedToSendBuffer=null; + + $signature=sprintf("", $name); + $this->write($signature); + $signature[6]="2"; + $this->client->currentArgumentsFormat = $signature; + } + function referenceEnd() { + $this->client->currentArgumentsFormat.=$format=""; + $this->write($format); + $this->finish(); + $this->client->currentCacheKey=null; + } + function createObjectBegin($name) { + $this->client->sendBuffer.=$this->client->preparedToSendBuffer; + if(JAVA_DEBUG) {echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";} + $this->client->preparedToSendBuffer=null; + + $signature=sprintf("", $name); + $this->write($signature); + $signature[6]="2"; + $this->client->currentArgumentsFormat = $signature; + } + function createObjectEnd() { + $this->client->currentArgumentsFormat.=$format=""; + $this->write($format); + $this->finish(); + $this->client->currentCacheKey=null; + } + function propertyAccessBegin($object, $method) { + $this->client->sendBuffer.=$this->client->preparedToSendBuffer; + if(JAVA_DEBUG) {echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";} + $this->client->preparedToSendBuffer=null; + + $this->write(sprintf("", $object, $method)); + $this->client->currentArgumentsFormat=""; + } + function propertyAccessEnd() { + $this->client->currentArgumentsFormat.=$format=""; + $this->write($format); + $this->finish(); + $this->client->currentCacheKey=null; + } + function invokeBegin($object, $method) { + $this->client->sendBuffer.=$this->client->preparedToSendBuffer; + if(JAVA_DEBUG) {echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";} + $this->client->preparedToSendBuffer=null; + + $this->write(sprintf("", $object, $method)); + $this->client->currentArgumentsFormat=""; + } + function invokeEnd() { + $this->client->currentArgumentsFormat.=$format=""; + $this->write($format); + $this->finish(); + $this->client->currentCacheKey=null; + } + function resultBegin() { + $this->client->sendBuffer.=$this->client->preparedToSendBuffer; + if(JAVA_DEBUG) {echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";} + $this->client->preparedToSendBuffer=null; + + $this->write(""); + } + function resultEnd() { + $this->client->currentCacheKey=null; + $this->write(""); + $this->flush(); + } + function writeString($name) { + $this->client->currentArgumentsFormat.=$format=""; + $this->write(sprintf($format, htmlspecialchars($name, ENT_COMPAT,"ISO-8859-1"))); + + } + function writeBoolean($boolean) { + $this->client->currentArgumentsFormat.=$format=""; + $this->write(sprintf($format, $boolean)); + } + function writeLong($l) { + $this->client->currentArgumentsFormat.=""; + if($l<0) { + $this->write(sprintf("",-$l)); + } else { + $this->write(sprintf("",$l)); + } + } + function writeULong($l) { + $this->client->currentArgumentsFormat.=$format=""; + $this->write(sprintf($format,$l)); + } + function writeDouble($d) { + $this->client->currentArgumentsFormat.=$format=""; + $this->write(sprintf($format, $d)); + } + function writeObject($object) { + $this->client->currentArgumentsFormat.=$format=""; + $this->write(sprintf($format, $object)); + } + + /* the following routines are not cached */ + function writeException($object, $str) { + $this->write(sprintf("",$object, htmlspecialchars($str, ENT_COMPAT,"ISO-8859-1"))); + } + function writeCompositeBegin_a() { + $this->write(""); + } + function writeCompositeBegin_h() { + $this->write(""); + } + function writeCompositeEnd() { + $this->write(""); + } + function writePairBegin_s($key) { + $this->write(sprintf("

", htmlspecialchars($key, ENT_COMPAT,"ISO-8859-1"))); + } + function writePairBegin_n($key) { + $this->write(sprintf("

",$key)); + } + function writePairBegin() { + $this->write("

"); + } + function writePairEnd() { + $this->write("

"); + } + function writeUnref($object) { + $this->client->sendBuffer.=$this->client->preparedToSendBuffer; + $this->client->preparedToSendBuffer=null; + $this->write(sprintf("", $object)); + } + function writeExitCode($code) { + $this->client->sendBuffer.=$this->client->preparedToSendBuffer; + $this->client->preparedToSendBuffer=null; + $this->write(sprintf("", 0xffffffff&$code)); + } + + function getServerName() { + return $this->serverName; + } } ?> diff --git a/src/main/java/io/soluble/pjb/bridge/DefaultOptions.java b/src/main/java/io/soluble/pjb/bridge/DefaultOptions.java index 489faef..c1a59c3 100644 --- a/src/main/java/io/soluble/pjb/bridge/DefaultOptions.java +++ b/src/main/java/io/soluble/pjb/bridge/DefaultOptions.java @@ -29,7 +29,7 @@ * @author jostb */ -final class DefaultOptions extends Options { +public final class DefaultOptions extends Options { @Override public boolean base64Data() { diff --git a/src/main/java/io/soluble/pjb/bridge/GlobalRef.java b/src/main/java/io/soluble/pjb/bridge/GlobalRef.java index 229b01f..be5f6d9 100644 --- a/src/main/java/io/soluble/pjb/bridge/GlobalRef.java +++ b/src/main/java/io/soluble/pjb/bridge/GlobalRef.java @@ -34,7 +34,7 @@ * n+1. This can be used to avoid round-trips by "guessing" the next * object ID, see java_begin_document()/java_end_document(). */ -class GlobalRef { +public class GlobalRef { /** * The default size (prime). diff --git a/src/main/java/io/soluble/pjb/bridge/JavaBridge.java b/src/main/java/io/soluble/pjb/bridge/JavaBridge.java index 63fca89..f1ad4c8 100644 --- a/src/main/java/io/soluble/pjb/bridge/JavaBridge.java +++ b/src/main/java/io/soluble/pjb/bridge/JavaBridge.java @@ -21,6 +21,8 @@ */ package io.soluble.pjb.bridge; +import io.soluble.pjb.bridge.http.IContext; + import java.beans.BeanInfo; import java.beans.Introspector; import java.beans.PropertyDescriptor; @@ -61,13 +63,13 @@ public final class JavaBridge implements Runnable { static final int DISPLAY_MAX_CHARS = 80; static final String PHPSESSION = "PHPSESSION"; static final String INTERNAL_PHPSESSION = "INTERNAL_PHPSESSION"; - static final HashMap SESSION_HASH = new HashMap(); + private static HashMap sessionHash = new HashMap(); - private final MethodCache methodCache = new MethodCache(); - private final ConstructorCache constructorCache = new ConstructorCache(); + public final MethodCache methodCache = new MethodCache(); + public final ConstructorCache constructorCache = new ConstructorCache(); boolean canModifySecurityPermission = true; // false if we detect that setAccessible is not possible - StringCache stringCache = new StringCache(this); + public StringCache stringCache = new StringCache(this); Options options; /** @@ -77,7 +79,7 @@ public final class JavaBridge implements Runnable { Throwable lastAsyncException; // reported by end_document() // array of objects in use in the current script - GlobalRef globalRef = new GlobalRef(); + public GlobalRef globalRef = new GlobalRef(); /** * For internal use only. The input stream for the current channel. @@ -205,6 +207,11 @@ public Options getOptions() { return options; } + public void setOptions(Options options) { + this.options = options; + } + + /** * Communication with client in a new thread */ @@ -1804,17 +1811,15 @@ public Object ObjectToString(Throwable ob, String trace) { return castToString(buf.toString()); } - private Object contextCache = null; + private IContext contextCache = null; + /** * Returns the JSR223 context. - * * @return The JSR223 context. */ - public Object getContext() { - if (contextCache != null) { - return contextCache; - } + public IContext getContext() { + if(contextCache!=null) return contextCache; return contextCache = sessionFactory.getContext(); } @@ -2355,4 +2360,33 @@ public void clearLastException() { lastException = lastAsyncException = null; } + + public GlobalRef getGlobalRef() { + return globalRef; + } + + public void setGlobalRef(GlobalRef globalRef) { + this.globalRef = globalRef; + } + + public Throwable getLastAsyncException() { + return lastAsyncException; + } + + public static HashMap getSessionHash() { + return sessionHash; + } + + public static void setSessionHash(HashMap sessionHash) { + JavaBridge.sessionHash = sessionHash; + } + + public StringCache getStringCache() { + return stringCache; + } + + public void setStringCache(StringCache stringCache) { + this.stringCache = stringCache; + } + } diff --git a/src/main/java/io/soluble/pjb/bridge/JavaInc.java b/src/main/java/io/soluble/pjb/bridge/JavaInc.java index 854941e..1ca2f25 100644 --- a/src/main/java/io/soluble/pjb/bridge/JavaInc.java +++ b/src/main/java/io/soluble/pjb/bridge/JavaInc.java @@ -562,6 +562,9 @@ public class JavaInc { "$val=$this->getResult();\n"+ "return $val;\n"+ "}\n"+ +"function setExitCode($code) {\n"+ +"if (isset($this->protocol)) $this->protocol->writeExitCode($code);\n"+ +"}\n"+ "function unref($object) {\n"+ "if (isset($this->protocol)) $this->protocol->writeUnref($object);\n"+ "}\n"+ @@ -1407,6 +1410,11 @@ public class JavaInc { "$this->client->preparedToSendBuffer=null;\n"+ "$this->write(sprintf(\"\",$object));\n"+ "}\n"+ +"function writeExitCode($code) {\n"+ +"$this->client->sendBuffer.=$this->client->preparedToSendBuffer;\n"+ +"$this->client->preparedToSendBuffer=null;\n"+ +"$this->write(sprintf(\"\",0xffffffff&$code));\n"+ +"}\n"+ "function getServerName() {\n"+ "return $this->serverName;\n"+ "}\n"+ diff --git a/src/main/java/io/soluble/pjb/bridge/MethodCache.java b/src/main/java/io/soluble/pjb/bridge/MethodCache.java index 0c481b9..367908f 100644 --- a/src/main/java/io/soluble/pjb/bridge/MethodCache.java +++ b/src/main/java/io/soluble/pjb/bridge/MethodCache.java @@ -31,7 +31,7 @@ * synchronization, so use this class per thread or per request * only. */ -final class MethodCache { +public final class MethodCache { Map map; static final Entry noCache = new NoCache(); diff --git a/src/main/java/io/soluble/pjb/bridge/ParserString.java b/src/main/java/io/soluble/pjb/bridge/ParserString.java index 2e4b4db..df5cdb7 100644 --- a/src/main/java/io/soluble/pjb/bridge/ParserString.java +++ b/src/main/java/io/soluble/pjb/bridge/ParserString.java @@ -29,7 +29,7 @@ * * @author jostb */ -final class ParserString { +public final class ParserString { protected byte[] string; protected int off; protected int length; diff --git a/src/main/java/io/soluble/pjb/bridge/PhpArray.java b/src/main/java/io/soluble/pjb/bridge/PhpArray.java index f2d68ab..1571885 100644 --- a/src/main/java/io/soluble/pjb/bridge/PhpArray.java +++ b/src/main/java/io/soluble/pjb/bridge/PhpArray.java @@ -29,7 +29,7 @@ import java.util.Set; import java.util.TreeMap; -final class PhpArray extends AbstractMap { // for PHP's array() +public final class PhpArray extends AbstractMap { // for PHP's array() private static final long serialVersionUID = 3905804162838115892L; private TreeMap t = new TreeMap(Request.PHP_ARRAY_KEY_COMPARATOR); private HashMap m = null; diff --git a/src/main/java/io/soluble/pjb/bridge/PhpExactNumber.java b/src/main/java/io/soluble/pjb/bridge/PhpExactNumber.java index b19a98c..4cb4a5b 100644 --- a/src/main/java/io/soluble/pjb/bridge/PhpExactNumber.java +++ b/src/main/java/io/soluble/pjb/bridge/PhpExactNumber.java @@ -22,7 +22,7 @@ package io.soluble.pjb.bridge; -final class PhpExactNumber extends Number { +public final class PhpExactNumber extends Number { /** * diff --git a/src/main/java/io/soluble/pjb/bridge/PhpProcedure.java b/src/main/java/io/soluble/pjb/bridge/PhpProcedure.java index b6b09a8..b7bd7a4 100644 --- a/src/main/java/io/soluble/pjb/bridge/PhpProcedure.java +++ b/src/main/java/io/soluble/pjb/bridge/PhpProcedure.java @@ -41,7 +41,7 @@ public final class PhpProcedure implements InvocationHandler { private Map names; protected String name; - protected PhpProcedure(IJavaBridgeFactory bridge, long object, String name, Map names) { + public PhpProcedure(IJavaBridgeFactory bridge, long object, String name, Map names) { this.bridge = bridge; this.object = object; this.names = names; @@ -123,7 +123,7 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl return invoke(proxy, method.getName(), method.getReturnType(), args); } - static long unwrap(Object ob) { + public static long unwrap(Object ob) { InvocationHandler handler = Proxy.getInvocationHandler(ob); PhpProcedure proc = (PhpProcedure) handler; return proc.object; diff --git a/src/main/java/io/soluble/pjb/bridge/PhpString.java b/src/main/java/io/soluble/pjb/bridge/PhpString.java index 24330a5..ed90ff2 100644 --- a/src/main/java/io/soluble/pjb/bridge/PhpString.java +++ b/src/main/java/io/soluble/pjb/bridge/PhpString.java @@ -26,7 +26,7 @@ /** * A php string is a UTF-8 coded byte array. */ -abstract class PhpString { +public abstract class PhpString { /** * Get the encoded string representation * diff --git a/src/main/java/io/soluble/pjb/bridge/Request.java b/src/main/java/io/soluble/pjb/bridge/Request.java index 2daea05..8f05e7a 100644 --- a/src/main/java/io/soluble/pjb/bridge/Request.java +++ b/src/main/java/io/soluble/pjb/bridge/Request.java @@ -51,7 +51,7 @@ public final class Request implements IDocHandler { * There is only one response handle for each request object. * response.reset() or response.flush() must be called at the end of each packet. */ - Response response = null; + public Response response = null; protected Object getGlobalRef(int i) { @@ -191,6 +191,11 @@ public boolean begin(ParserTag[] tag) { arg.id.parseID(st[0]); break; } + case 'Z': { + arg.type=ch; + bridge.getContext().setExitCode(st[0].getIntValue()); + break; + } case 'X': { arg = new CompositeArg(arg); diff --git a/src/main/java/io/soluble/pjb/bridge/Session.java b/src/main/java/io/soluble/pjb/bridge/Session.java index b80b7c5..693729e 100644 --- a/src/main/java/io/soluble/pjb/bridge/Session.java +++ b/src/main/java/io/soluble/pjb/bridge/Session.java @@ -79,9 +79,9 @@ public boolean isNew() { public void destroy() { sessionCount--; - synchronized (JavaBridge.SESSION_HASH) { - if (JavaBridge.SESSION_HASH != null) - JavaBridge.SESSION_HASH.remove(name); + synchronized (JavaBridge.getSessionHash()) { + if (JavaBridge.getSessionHash() != null) + JavaBridge.getSessionHash().remove(name); } } @@ -107,9 +107,9 @@ public Map getAll() { * see #CHECK_SESSION_TIMEOUT */ static synchronized void expire() { - if (JavaBridge.SESSION_HASH == null) return; - synchronized (JavaBridge.SESSION_HASH) { - for (Iterator e = JavaBridge.SESSION_HASH.values().iterator(); e.hasNext(); ) { + if (JavaBridge.getSessionHash() == null) return; + synchronized (JavaBridge.getSessionHash()) { + for (Iterator e = JavaBridge.getSessionHash().values().iterator(); e.hasNext(); ) { Session ref = (Session) e.next(); if ((ref.timeout > 0) && (ref.lastAccessedTime + ref.timeout <= System.currentTimeMillis())) { sessionCount--; @@ -124,9 +124,9 @@ static synchronized void expire() { * Expires all sessions immediately. */ public static void reset() { - if (JavaBridge.SESSION_HASH == null) return; - synchronized (JavaBridge.SESSION_HASH) { - for (Iterator e = JavaBridge.SESSION_HASH.values().iterator(); e.hasNext(); ) { + if (JavaBridge.getSessionHash() == null) return; + synchronized (JavaBridge.getSessionHash()) { + for (Iterator e = JavaBridge.getSessionHash().values().iterator(); e.hasNext(); ) { Session ref = (Session) e.next(); sessionCount--; e.remove(); diff --git a/src/main/java/io/soluble/pjb/bridge/SessionFactory.java b/src/main/java/io/soluble/pjb/bridge/SessionFactory.java index 0aa0299..bfecfed 100644 --- a/src/main/java/io/soluble/pjb/bridge/SessionFactory.java +++ b/src/main/java/io/soluble/pjb/bridge/SessionFactory.java @@ -62,17 +62,17 @@ private static SessionTimer getSessionTimer() { } private ISession session(String name, short clientIsNew, int timeout) { - synchronized (JavaBridge.SESSION_HASH) { + synchronized (JavaBridge.getSessionHash()) { Session ref = null; - if (!JavaBridge.SESSION_HASH.containsKey(name)) { + if (!JavaBridge.getSessionHash().containsKey(name)) { ref = new Session(name); - JavaBridge.SESSION_HASH.put(name, ref); + JavaBridge.getSessionHash().put(name, ref); } else { - ref = (Session) JavaBridge.SESSION_HASH.get(name); + ref = (Session) JavaBridge.getSessionHash().get(name); if (clientIsNew == ISession.SESSION_CREATE_NEW) { // client side gc'ed, destroy server ref now! ref.destroy(); ref = new Session(name); - JavaBridge.SESSION_HASH.put(name, ref); + JavaBridge.getSessionHash().put(name, ref); } else { ref.isNew = false; } diff --git a/src/main/java/io/soluble/pjb/bridge/SimplePhpString.java b/src/main/java/io/soluble/pjb/bridge/SimplePhpString.java index 4479bcf..fbeb707 100644 --- a/src/main/java/io/soluble/pjb/bridge/SimplePhpString.java +++ b/src/main/java/io/soluble/pjb/bridge/SimplePhpString.java @@ -22,7 +22,7 @@ package io.soluble.pjb.bridge; -final class SimplePhpString extends PhpString { +public final class SimplePhpString extends PhpString { String s; JavaBridge bridge; diff --git a/src/main/java/io/soluble/pjb/bridge/StringCache.java b/src/main/java/io/soluble/pjb/bridge/StringCache.java index c1669e0..13f5a95 100644 --- a/src/main/java/io/soluble/pjb/bridge/StringCache.java +++ b/src/main/java/io/soluble/pjb/bridge/StringCache.java @@ -33,7 +33,7 @@ * synchronization, so use this class per thread or per request * only. */ -final class StringCache { +public final class StringCache { private Map map; private JavaBridge bridge; diff --git a/src/main/java/io/soluble/pjb/bridge/http/Context.java b/src/main/java/io/soluble/pjb/bridge/http/Context.java index f861009..cb8e213 100644 --- a/src/main/java/io/soluble/pjb/bridge/http/Context.java +++ b/src/main/java/io/soluble/pjb/bridge/http/Context.java @@ -66,6 +66,9 @@ public class Context implements IManaged, Invocable, IContext { */ private Map engineScope; + private int exitCode; + + protected Context() { } @@ -396,4 +399,13 @@ public String getRedirectString(String webPath) { public String getRedirectURL(String webPath) { return "http://127.0.0.1:" + getSocketName() + webPath; } + + @Override + public void setExitCode(int exitCode) { + this.exitCode = exitCode; + } + @Override + public int getExitCode() { + return exitCode; + } } diff --git a/src/main/java/io/soluble/pjb/bridge/http/IContext.java b/src/main/java/io/soluble/pjb/bridge/http/IContext.java index a35a551..50caeab 100644 --- a/src/main/java/io/soluble/pjb/bridge/http/IContext.java +++ b/src/main/java/io/soluble/pjb/bridge/http/IContext.java @@ -260,4 +260,8 @@ public abstract void setAttribute(String name, Object value, int scope) * @return the socket name */ public String getSocketName(); + + public void setExitCode(int intValue); + + public int getExitCode(); } \ No newline at end of file diff --git a/src/main/java/io/soluble/pjb/script/AbstractPhpScriptContext.java b/src/main/java/io/soluble/pjb/script/AbstractPhpScriptContext.java index 40d8cae..e711075 100644 --- a/src/main/java/io/soluble/pjb/script/AbstractPhpScriptContext.java +++ b/src/main/java/io/soluble/pjb/script/AbstractPhpScriptContext.java @@ -46,6 +46,8 @@ public AbstractPhpScriptContext(ScriptContext ctx) { protected Continuation kont; + private int exitCode; + /** * {@inheritDoc} */ @@ -129,4 +131,17 @@ public void setWriter(Writer writer) { public void setErrorWriter(Writer writer) { super.setErrorWriter(this.errorWriter = new PhpScriptWriter(new WriterOutputStream(writer))); } + + + @Override + public void setExitCode(int exitCode) { + this.exitCode = exitCode; + + } + @Override + public int getExitCode() { + return exitCode; + } + + } diff --git a/src/main/java/io/soluble/pjb/script/PhpScriptContextDecorator.java b/src/main/java/io/soluble/pjb/script/PhpScriptContextDecorator.java index 99e28dc..fda5e43 100644 --- a/src/main/java/io/soluble/pjb/script/PhpScriptContextDecorator.java +++ b/src/main/java/io/soluble/pjb/script/PhpScriptContextDecorator.java @@ -321,4 +321,17 @@ public ContextServer getContextServer() { public void startContinuation() { ctx.startContinuation(); } + + /**{@inheritDoc}*/ + @Override + public void setExitCode(int exitCode) { + ctx.setExitCode(exitCode); + } + + /**{@inheritDoc}*/ + @Override + public int getExitCode() { + return ctx.getExitCode(); + } + } diff --git a/src/main/resources/META-INF/java/Java.inc b/src/main/resources/META-INF/java/Java.inc index 5cc52af..148bbe2 100644 --- a/src/main/resources/META-INF/java/Java.inc +++ b/src/main/resources/META-INF/java/Java.inc @@ -560,6 +560,9 @@ $this->protocol->invokeEnd(); $val=$this->getResult(); return $val; } +function setExitCode($code) { +if (isset($this->protocol)) $this->protocol->writeExitCode($code); +} function unref($object) { if (isset($this->protocol)) $this->protocol->writeUnref($object); } @@ -1405,6 +1408,11 @@ $this->client->sendBuffer.=$this->client->preparedToSendBuffer; $this->client->preparedToSendBuffer=null; $this->write(sprintf("",$object)); } +function writeExitCode($code) { +$this->client->sendBuffer.=$this->client->preparedToSendBuffer; +$this->client->preparedToSendBuffer=null; +$this->write(sprintf("",0xffffffff&$code)); +} function getServerName() { return $this->serverName; } diff --git a/src/main/webapp/java/Java.inc b/src/main/webapp/java/Java.inc index 5cc52af..148bbe2 100644 --- a/src/main/webapp/java/Java.inc +++ b/src/main/webapp/java/Java.inc @@ -560,6 +560,9 @@ $this->protocol->invokeEnd(); $val=$this->getResult(); return $val; } +function setExitCode($code) { +if (isset($this->protocol)) $this->protocol->writeExitCode($code); +} function unref($object) { if (isset($this->protocol)) $this->protocol->writeUnref($object); } @@ -1405,6 +1408,11 @@ $this->client->sendBuffer.=$this->client->preparedToSendBuffer; $this->client->preparedToSendBuffer=null; $this->write(sprintf("",$object)); } +function writeExitCode($code) { +$this->client->sendBuffer.=$this->client->preparedToSendBuffer; +$this->client->preparedToSendBuffer=null; +$this->write(sprintf("",0xffffffff&$code)); +} function getServerName() { return $this->serverName; } From 2f161c3e3af97d4bd1935fa4351200f5aebf59e2 Mon Sep 17 00:00:00 2001 From: sebastien Date: Sun, 23 Apr 2017 20:12:26 +0200 Subject: [PATCH 2/8] Merge changes from upstream 7.1.3 (wip) --- CHANGELOG.md | 8 ++------ build.gradle | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 009e01d..424deeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,19 +3,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/). -## 7.1.0 (TBD) +## 7.1.3 (TBD) This release will include mergers from the original php-java-bridge 7.1.3 -when stabilized. +when stabilized. Only changes regarding php->java have been merged (not java->php). ### Added - `Client->setExitCode()`, `Protocol->setExitCode()` from upstream. - -### Changed - - ### Updated - Gradle wrapper updated to 3.5.0 diff --git a/build.gradle b/build.gradle index 77dbacd..05f5386 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ apply plugin: 'maven-publish' group = "io.soluble.pjb" archivesBaseName = 'php-java-bridge' //version = "6.2.11" -version = "7.0.1-SNAPSHOT" +version = "7.1.3-SNAPSHOT" description = "PHPJavaBridge server (soluble fork)" ext { From 0b20bfcfcaaa77930cc7dcaee3db1ffdbd102d9e Mon Sep 17 00:00:00 2001 From: sebastien Date: Sun, 23 Apr 2017 20:21:52 +0200 Subject: [PATCH 3/8] Fix build with javadoc --- src/main/java/io/soluble/pjb/bridge/GlobalRef.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/soluble/pjb/bridge/GlobalRef.java b/src/main/java/io/soluble/pjb/bridge/GlobalRef.java index be5f6d9..27f36ef 100644 --- a/src/main/java/io/soluble/pjb/bridge/GlobalRef.java +++ b/src/main/java/io/soluble/pjb/bridge/GlobalRef.java @@ -26,7 +26,7 @@ /** * A global array of object references that the client keeps during - * the connection (int -> Object mappings). After connection shutdown + * the connection (int Object mappings). After connection shutdown * the request-handling bridge instance and its global ref array are * destroyed. *

From 9296a07f2d141dd0b33e1784eaea3b9b26a4cb67 Mon Sep 17 00:00:00 2001 From: sebastien Date: Sun, 23 Apr 2017 20:32:33 +0200 Subject: [PATCH 4/8] Fix build with javadoc --- src/main/java/io/soluble/pjb/bridge/MethodCache.java | 2 +- src/main/java/io/soluble/pjb/bridge/ParserString.java | 2 -- src/main/java/io/soluble/pjb/bridge/StringCache.java | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/soluble/pjb/bridge/MethodCache.java b/src/main/java/io/soluble/pjb/bridge/MethodCache.java index 367908f..a64b1d3 100644 --- a/src/main/java/io/soluble/pjb/bridge/MethodCache.java +++ b/src/main/java/io/soluble/pjb/bridge/MethodCache.java @@ -27,7 +27,7 @@ import java.util.Map; /** - * Cache [Entry(object, method, parameters) -> Method]. No + * Cache [Entry(object, method, parameters) - Method]. No * synchronization, so use this class per thread or per request * only. */ diff --git a/src/main/java/io/soluble/pjb/bridge/ParserString.java b/src/main/java/io/soluble/pjb/bridge/ParserString.java index df5cdb7..a5e5708 100644 --- a/src/main/java/io/soluble/pjb/bridge/ParserString.java +++ b/src/main/java/io/soluble/pjb/bridge/ParserString.java @@ -80,7 +80,6 @@ public String getUTF8StringValue() { * Returns the string encoded via java_set_file_encoding(). * * @return The encoded string value. - * @see io.soluble.pjb.Options#getEncoding() */ public String getStringValue() { return bridge.getString(string, off, length); @@ -90,7 +89,6 @@ public String getStringValue() { * Returns the cached string encoded via java_set_file_encoding(). * * @return The encoded string value. - * @see io.soluble.pjb.Options#getEncoding() */ public String getCachedStringValue() { return bridge.getCachedString(string, off, length); diff --git a/src/main/java/io/soluble/pjb/bridge/StringCache.java b/src/main/java/io/soluble/pjb/bridge/StringCache.java index 13f5a95..57c2d92 100644 --- a/src/main/java/io/soluble/pjb/bridge/StringCache.java +++ b/src/main/java/io/soluble/pjb/bridge/StringCache.java @@ -29,7 +29,7 @@ import java.util.Map; /** - * Cache [Entry(byte[], enc) -> String]. No + * Cache [Entry(byte[], enc) - String]. No * synchronization, so use this class per thread or per request * only. */ From cf9dc629968a4ade981a87ddc2cc879fdc5c9737 Mon Sep 17 00:00:00 2001 From: sebastien Date: Sun, 23 Apr 2017 20:44:21 +0200 Subject: [PATCH 5/8] Prep 7.1.3 --- src/main/webapp/index.jsp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/index.jsp b/src/main/webapp/index.jsp index 32e298c..b19a38b 100644 --- a/src/main/webapp/index.jsp +++ b/src/main/webapp/index.jsp @@ -16,7 +16,7 @@