Client::begin()   D
last analyzed

Complexity

Conditions 18
Paths 18

Size

Total Lines 75
Code Lines 67

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 53
CRAP Score 20.0381

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 18
eloc 67
c 1
b 0
f 0
nc 18
nop 2
dl 0
loc 75
ccs 53
cts 65
cp 0.8154
crap 20.0381
rs 4.8666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
/**
5
 * soluble-japha / PHPJavaBridge driver client.
6
 *
7
 * Refactored version of phpjababridge's Java.inc file compatible
8
 * with php java bridge 6.2
9
 *
10
 *
11
 * @credits   http://php-java-bridge.sourceforge.net/pjb/
12
 *
13
 * @see      http://github.com/belgattitude/soluble-japha
14
 *
15
 * @author Jost Boekemeier
16
 * @author Vanvelthem Sébastien (refactoring and fixes from original implementation)
17
 * @license   MIT
18
 *
19
 * The MIT License (MIT)
20
 * Copyright (c) 2014-2017 Jost Boekemeier
21
 * Permission is hereby granted, free of charge, to any person obtaining a copy
22
 * of this software and associated documentation files (the "Software"), to deal
23
 * in the Software without restriction, including without limitation the rights
24
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25
 * copies of the Software, and to permit persons to whom the Software is
26
 * furnished to do so, subject to the following conditions:
27
 *
28
 * The above copyright notice and this permission notice shall be included in
29
 * all copies or substantial portions of the Software.
30
 *
31
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37
 * THE SOFTWARE.
38
 */
39
40
namespace Soluble\Japha\Bridge\Driver\Pjb62;
41
42
use ArrayObject;
43
use Psr\Log\LoggerInterface;
44
use Soluble\Japha\Bridge\Exception\JavaException;
45
use Soluble\Japha\Interfaces;
46
use Soluble\Japha\Bridge\Driver\Pjb62\Utils\HelperFunctions;
47
48
class Client
49
{
50
    public const PARAM_JAVA_HOSTS = 'JAVA_HOSTS';
51
    public const PARAM_JAVA_SERVLET = 'JAVA_SERVLET';
52
    public const PARAM_JAVA_AUTH_USER = 'JAVA_AUTH_USER';
53
    public const PARAM_JAVA_AUTH_PASSWORD = 'JAVA_AUTH_PASSWORD';
54
    public const PARAM_JAVA_DISABLE_AUTOLOAD = 'JAVA_DISABLE_AUTOLOAD';
55
    public const PARAM_JAVA_PREFER_VALUES = 'JAVA_PREFER_VALUES';
56
    public const PARAM_JAVA_SEND_SIZE = 'JAVA_SEND_SIZE';
57
    public const PARAM_JAVA_RECV_SIZE = 'JAVA_RECV_SIZE';
58
    public const PARAM_JAVA_LOG_LEVEL = 'JAVA_LOG_LEVEL';
59
    public const PARAM_JAVA_INTERNAL_ENCODING = 'JAVA_INTERNAL_ENCODING';
60
    public const PARAM_XML_PARSER_FORCE_SIMPLE_PARSER = 'XML_PARSER_FORCE_SIMPLE_PARSER';
61
    public const PARAM_USE_PERSISTENT_CONNECTION = 'USE_PERSISTENT_CONNECTION';
62
63
    public const DEFAULT_PARAMS = [
64
        self::PARAM_JAVA_HOSTS => 'localhost',
65
        self::PARAM_JAVA_SERVLET => 'JavaBridge/servlet.phpjavabridge',
66
        self::PARAM_JAVA_AUTH_USER => null,
67
        self::PARAM_JAVA_AUTH_PASSWORD => null,
68
        self::PARAM_JAVA_DISABLE_AUTOLOAD => true,
69
        self::PARAM_JAVA_PREFER_VALUES => true,
70
        self::PARAM_JAVA_SEND_SIZE => 8192,
71
        self::PARAM_JAVA_RECV_SIZE => 8192,
72
        self::PARAM_JAVA_LOG_LEVEL => null,
73
        self::PARAM_JAVA_INTERNAL_ENCODING => 'UTF-8',
74
        self::PARAM_XML_PARSER_FORCE_SIMPLE_PARSER => false,
75
        self::PARAM_USE_PERSISTENT_CONNECTION => false
76
    ];
77
78
    /**
79
     * @var array
80
     */
81
    public $RUNTIME;
82
    public $result;
83
    public $exception;
84
    /**
85
     * @var ParserFactory
86
     */
87
    public $parser;
88
89
    /**
90
     * @var Arg|CompositeArg
91
     */
92
    public $simpleArg;
93
94
    /**
95
     * @var CompositeArg
96
     */
97
    public $compositeArg;
98
99
    /**
100
     * @var SimpleFactory
101
     */
102
    public $simpleFactory;
103
104
    /**
105
     * @var ProxyFactory
106
     */
107
    public $proxyFactory;
108
109
    /**
110
     * @var IteratorProxyFactory
111
     */
112
    public $iteratorProxyFactory;
113
114
    /**
115
     * @var ArrayProxyFactory
116
     */
117
    public $arrayProxyFactory;
118
119
    /**
120
     * @var ExceptionProxyFactory
121
     */
122
    public $exceptionProxyFactory;
123
124
    /**
125
     * @var ThrowExceptionProxyFactory
126
     */
127
    public $throwExceptionProxyFactory;
128
129
    /**
130
     * @var Arg|CompositeArg
131
     */
132
    public $arg;
133
    /**
134
     * @var int
135
     */
136
    public $asyncCtx;
137
138
    /**
139
     * @var int
140
     */
141
    public $cancelProxyCreationTag;
142
143
    /**
144
     * @var GlobalRef
145
     */
146
    public $globalRef;
147
    public $stack;
148
    /**
149
     * @var array
150
     */
151
    public $defaultCache = [];
152
    /**
153
     * @var array
154
     */
155
    public $asyncCache = [];
156
    /**
157
     * @var array
158
     */
159
    public $methodCache = [];
160
    public $isAsync = 0;
161
    /**
162
     * @var string|null
163
     */
164
    public $currentCacheKey;
165
166
    /**
167
     * @var string
168
     */
169
    public $currentArgumentsFormat;
170
    public $cachedJavaPrototype;
171
172
    /**
173
     * @var string|null
174
     */
175
    public $sendBuffer;
176
    /**
177
     * @var string|null
178
     */
179
    public $preparedToSendBuffer;
180
    public $inArgs;
181
182
    /**
183
     * @var int
184
     */
185
    protected $idx;
186
187
    /**
188
     * @var Protocol
189
     */
190
    public $protocol;
191
192
    /**
193
     * @var array
194
     */
195
    protected $cachedValues = [];
196
197
    /**
198
     * @var ArrayObject
199
     */
200
    protected $params;
201
202
    /**
203
     * @var string
204
     */
205
    public $java_servlet;
206
207
    /**
208
     * @var string
209
     */
210
    public $java_hosts;
211
212
    /**
213
     * @var int
214
     */
215
    public $java_recv_size;
216
217
    /**
218
     * @var int
219
     */
220
    public $java_send_size;
221
222
    /**
223
     * @var LoggerInterface
224
     */
225
    protected $logger;
226
227
    /**
228
     * @param ArrayObject $params
229
     */
230 30
    public function __construct(ArrayObject $params, LoggerInterface $logger)
231
    {
232 30
        $this->params = new ArrayObject(array_merge(self::DEFAULT_PARAMS, (array) $params));
233
234 30
        $this->logger = $logger;
235
236 30
        $this->java_send_size = $this->params[self::PARAM_JAVA_SEND_SIZE];
237 30
        $this->java_recv_size = $this->params[self::PARAM_JAVA_RECV_SIZE];
238
239 30
        $this->java_hosts = $this->params['JAVA_HOSTS'];
240 30
        $this->java_servlet = $this->params['JAVA_SERVLET'];
241
242 30
        $this->RUNTIME = [];
243 30
        $this->RUNTIME['NOTICE'] = '***USE echo $adapter->getDriver()->inspect(jVal) OR print_r($adapter->values(jVal)) TO SEE THE CONTENTS OF THIS JAVA OBJECT!***';
244 30
        $this->parser = new ParserFactory($this, $params['XML_PARSER_FORCE_SIMPLE_PARSER'] ?? false);
245 30
        $this->protocol = new Protocol($this, $this->java_hosts, $this->java_servlet, $this->java_recv_size, $this->java_send_size);
246 28
        $this->simpleFactory = new SimpleFactory($this);
247 28
        $this->proxyFactory = new ProxyFactory($this);
248 28
        $this->arrayProxyFactory = new ArrayProxyFactory($this);
249 28
        $this->iteratorProxyFactory = new IteratorProxyFactory($this);
250 28
        $this->exceptionProxyFactory = new ExceptionProxyFactory($this);
251 28
        $this->throwExceptionProxyFactory = new ThrowExceptionProxyFactory($this);
252 28
        $this->cachedJavaPrototype = new JavaProxyProxy($this);
253 28
        $this->simpleArg = new Arg($this);
254 28
        $this->globalRef = new GlobalRef();
255 28
        $this->asyncCtx = $this->cancelProxyCreationTag = 0;
256 28
        $this->methodCache = $this->defaultCache;
257 28
        $this->inArgs = false;
258
259 28
        $this->cachedValues = [
260
            'getContext' => null,
261
            'getServerName' => null
262
        ];
263 28
    }
264
265 3
    public function getLogger(): LoggerInterface
266
    {
267 3
        return $this->logger;
268
    }
269
270 114
    public function read($size): string
271
    {
272 114
        return $this->protocol->read($size);
273
    }
274
275 1
    public function setDefaultHandler(): void
276
    {
277 1
        $this->methodCache = $this->defaultCache;
278 1
    }
279
280 1
    public function setAsyncHandler(): void
281
    {
282 1
        $this->methodCache = $this->asyncCache;
283 1
    }
284
285
    /**
286
     * Handle request.
287
     *
288
     * @throws Exception\RuntimeException
289
     */
290 114
    public function handleRequests(): void
291
    {
292 114
        $tail_call = false;
293
        do {
294 114
            $this->arg = $this->simpleArg;
295 114
            $this->stack = [$this->arg];
296 114
            $this->idx = 0;
297 114
            $this->parser->parse();
298 113
            if (count($this->stack) > 1) {
299
                $arg = array_pop($this->stack);
300
                if ($arg instanceof ApplyArg) {
301
                    $this->apply($arg);
302
                } else {
303
                    $msg = 'Error: $arg should be of type ApplyArg, error in client';
304
                    $this->logger->critical($msg);
305
                    throw new Exception\RuntimeException($msg);
306
                }
307
                $tail_call = true;
308
            }
309 113
            $this->stack = null;
310 113
        } while ($tail_call);
311 113
    }
312
313
    /**
314
     * @param bool $wrap
315
     */
316 113
    public function getWrappedResult($wrap)
317
    {
318 113
        return $this->simpleArg->getResult($wrap);
319
    }
320
321 88
    public function getInternalResult(): JavaProxy
322
    {
323 88
        return $this->getWrappedResult(false);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getWrappedResult(false) returns the type Soluble\Japha\Bridge\Driver\Pjb62\JavaType which includes types incompatible with the type-hinted return Soluble\Japha\Bridge\Driver\Pjb62\JavaProxy.
Loading history...
324
    }
325
326 106
    public function getResult()
327
    {
328 106
        return $this->getWrappedResult(true);
329
    }
330
331
    /**
332
     * @param string $type
333
     *
334
     * @return SimpleFactory
335
     */
336 111
    protected function getProxyFactory(string $type): SimpleFactory
337
    {
338 111
        switch ($type[0]) {
339 111
            case 'E':
340 23
                $factory = $this->exceptionProxyFactory;
341 23
                break;
342 110
            case 'C':
343 5
                $factory = $this->iteratorProxyFactory;
344 5
                break;
345 109
            case 'A':
346 32
                $factory = $this->arrayProxyFactory;
347 32
                break;
348 104
            case 'O':
349
            default:
350 104
                $factory = $this->proxyFactory;
351
        }
352
353 111
        return $factory;
354
    }
355
356
    /**
357
     * @param Arg          $arg
358
     * @param CompositeArg $newArg
359
     */
360 15
    private function link(&$arg, &$newArg): void
361
    {
362 15
        $arg->linkResult($newArg->val);
363 15
        $newArg->parentArg = $arg;
364 15
    }
365
366
    /**
367
     * @param string $str
368
     *
369
     * @return int
370
     */
371 111
    protected function getExact($str)
372
    {
373 111
        return (int) hexdec($str);
374
    }
375
376
    /**
377
     * @param string $str
378
     *
379
     * @return mixed
380
     */
381 3
    private function getInexact($str)
382
    {
383 3
        $val = null;
384 3
        sscanf($str, '%e', $val);
385
386 3
        return $val;
387
    }
388
389
    /**
390
     * @param string $name
391
     * @param array  $st   param
392
     */
393 113
    public function begin(string $name, array $st): void
394
    {
395 113
        $arg = $this->arg;
396 113
        $code = $name[0];
397 113
        switch ($code) {
398 113
            case 'A':
399
                $object = $this->globalRef->get($this->getExact($st['v']));
400
                $newArg = new ApplyArg($this, 'A', $this->parser->getData($st['m']), $this->parser->getData($st['p']), $object, $this->getExact($st['n']));
401
                $this->link($arg, $newArg);
402
                array_push($this->stack, $this->arg = $newArg);
403
                break;
404 113
            case 'X':
405 15
                $newArg = new CompositeArg($this, $st['t']);
406 15
                $this->link($arg, $newArg);
407 15
                array_push($this->stack, $this->arg = $newArg);
408 15
                break;
409 113
            case 'P':
410 15
                if ($arg->type === 'H') {
411 10
                    $s = $st['t'];
412 10
                    if ($s[0] === 'N') {
413 6
                        $arg->setIndex($this->getExact($st['v']));
0 ignored issues
show
introduced by
The method setIndex() does not exist on Soluble\Japha\Bridge\Driver\Pjb62\Arg. Maybe you want to declare this class abstract? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

413
                        $arg->/** @scrutinizer ignore-call */ 
414
                              setIndex($this->getExact($st['v']));
Loading history...
414
                    } else {
415 10
                        $arg->setIndex($this->parser->getData($st['v']));
416
                    }
417
                } else {
418 5
                    $arg->setNextIndex();
0 ignored issues
show
introduced by
The method setNextIndex() does not exist on Soluble\Japha\Bridge\Driver\Pjb62\Arg. Maybe you want to declare this class abstract? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

418
                    $arg->/** @scrutinizer ignore-call */ 
419
                          setNextIndex();
Loading history...
419
                }
420 15
                break;
421 113
            case 'S':
422 88
                $arg->setResult($this->parser->getData($st['v']));
423 88
                break;
424 111
            case 'B':
425 16
                $s = $st['v'];
426 16
                $arg->setResult($s[0] === 'T');
427 16
                break;
428 111
            case 'L':
429 21
                $sign = $st['p'];
430 21
                $val = $this->getExact($st['v']);
431 21
                if ($sign[0] === 'A') {
432 1
                    $val *= -1;
433
                }
434 21
                $arg->setResult($val);
435 21
                break;
436 111
            case 'D':
437 3
                $arg->setResult($this->getInexact($st['v']));
438 3
                break;
439 111
            case 'V':
440 30
                if ($st['n'] !== 'T') {
441
                    $arg->setVoidSignature();
442
                }
443
                // possible bugfix, the break was missing here
444 30
                break;
445 111
            case 'N':
446 10
                $arg->setResult(null);
447 10
                break;
448 111
            case 'F':
449 8
                break;
450 111
            case 'O':
451 111
                $arg->setFactory($this->getProxyFactory($st['p']));
452 111
                $arg->setResult($this->asyncCtx = $this->getExact($st['v']));
453 111
                if ($st['n'] !== 'T') {
454
                    $arg->setSignature($st['m']);
455
                }
456 111
                break;
457 22
            case 'E':
458 22
                $arg->setFactory($this->throwExceptionProxyFactory);
459 22
                $arg->setException($st['m']);
460 22
                $arg->setResult($this->asyncCtx = $this->getExact($st['v']));
461 22
                break;
462
            default:
463
                $this->protocol->handler->shutdownBrokenConnection(
464
                    sprintf(
465
                        'Parser error, check the backend for details, "$name": %s, "$st": %s',
466
                        $name,
467
                        json_encode($st)
468
                    )
469
                );
470
        }
471 113
    }
472
473
    /**
474
     * @param string $name
475
     */
476 112
    public function end(string $name): void
477
    {
478 112
        switch ($name[0]) {
479 112
            case 'X':
480 15
                $frame = array_pop($this->stack);
481 15
                $this->arg = $frame->parentArg;
482 15
                break;
483
        }
484 112
    }
485
486
    /**
487
     * @throws JavaException
488
     *
489
     * @param mixed $arg
490
     */
491 110
    protected function writeArg($arg): void
492
    {
493 110
        if (is_string($arg)) {
494 85
            $this->protocol->writeString($arg);
495 102
        } elseif (is_object($arg)) {
496 98
            if (!$arg instanceof JavaType) {
497 1
                $msg = "Client failed to writeArg(), IllegalArgument 'arg:".get_class($arg)."' not a Java object, using NULL instead";
498 1
                $this->logger->error("[soluble-japha] $msg (".__METHOD__.')');
499
                //trigger_error($msg, E_USER_WARNING);
500 1
                $this->protocol->writeObject(null);
501
            } else {
502 98
                $this->protocol->writeObject($arg->get__java());
503
            }
504 33
        } elseif (null === $arg) {
505 2
            $this->protocol->writeObject(null);
506 32
        } elseif (is_bool($arg)) {
507 3
            $this->protocol->writeBoolean($arg);
508 32
        } elseif (is_int($arg)) {
509 25
            $this->protocol->writeLong($arg);
510 18
        } elseif (is_float($arg)) {
511 4
            $this->protocol->writeDouble($arg);
512 15
        } elseif (is_array($arg)) {
513 14
            $wrote_begin = false;
514 14
            foreach ($arg as $key => $val) {
515 13
                if (is_string($key)) {
516 10
                    if (!$wrote_begin) {
517 10
                        $wrote_begin = true;
518 10
                        $this->protocol->writeCompositeBegin_h();
519
                    }
520 10
                    $this->protocol->writePairBegin_s($key);
521 10
                    $this->writeArg($val);
522 10
                    $this->protocol->writePairEnd();
523
                } else {
524 7
                    if (!$wrote_begin) {
525 7
                        $wrote_begin = true;
526 7
                        $this->protocol->writeCompositeBegin_h();
527
                    }
528 7
                    $this->protocol->writePairBegin_n($key);
529 7
                    $this->writeArg($val);
530 7
                    $this->protocol->writePairEnd();
531
                }
532
            }
533 14
            if (!$wrote_begin) {
534 1
                $this->protocol->writeCompositeBegin_a();
535
            }
536 14
            $this->protocol->writeCompositeEnd();
537
        }
538 110
    }
539
540
    /**
541
     * @param array $args
542
     */
543 114
    protected function writeArgs(array $args): void
544
    {
545 114
        $this->inArgs = true;
546 114
        foreach ($args as $arg) {
547 110
            $this->writeArg($arg);
548
        }
549 114
        $this->inArgs = false;
550 114
    }
551
552
    /**
553
     * @param string $name java class name, i.e java.math.BigInteger
554
     * @param array  $args
555
     *
556
     * @return JavaProxy
557
     */
558 72
    public function createObject(string $name, array $args): JavaProxy
559
    {
560 72
        $this->protocol->createObjectBegin($name);
561 72
        $this->writeArgs($args);
562 72
        $this->protocol->createObjectEnd();
563
564 71
        return $this->getInternalResult();
565
    }
566
567
    /**
568
     * @param string $name java class name, i.e java.math.BigInteger
569
     * @param array  $args
570
     *
571
     * @return JavaProxy
572
     */
573 24
    public function referenceObject(string $name, array $args): JavaProxy
574
    {
575 24
        $this->protocol->referenceBegin($name);
576 24
        $this->writeArgs($args);
577 24
        $this->protocol->referenceEnd();
578 24
        $val = $this->getInternalResult();
579
580 19
        return $val;
581
    }
582
583
    /**
584
     * @param int    $object
585
     * @param string $property
586
     *
587
     * @return mixed
588
     */
589 24
    public function getProperty(int $object, string $property)
590
    {
591 24
        $this->protocol->propertyAccessBegin($object, $property);
592 24
        $this->protocol->propertyAccessEnd();
593
594 24
        return $this->getResult();
595
    }
596
597
    /**
598
     * @param int    $object
599
     * @param string $property
600
     * @param mixed  $arg
601
     */
602 2
    public function setProperty(int $object, string $property, $arg): void
603
    {
604 2
        $this->protocol->propertyAccessBegin($object, $property);
605 2
        $this->writeArg($arg);
606 2
        $this->protocol->propertyAccessEnd();
607 2
        $this->getResult();
608
    }
609
610
    /**
611
     * Invoke a method on java object.
612
     *
613
     * @param int    $object_id a java object or type
614
     * @param string $method    method name
615
     * @param array  $args      arguments to send with method
616
     *
617
     * @return mixed
618
     */
619 106
    public function invokeMethod(int $object_id, string $method, array $args = [])
620
    {
621 106
        $this->protocol->invokeBegin($object_id, $method);
622 106
        $this->writeArgs($args);
623
624 106
        $this->protocol->invokeEnd();
625 106
        $val = $this->getResult();
626
627 106
        return $val;
628
    }
629
630
    /**
631
     * Write exit code.
632
     *
633
     * @param int $code
634
     */
635
    public function setExitCode(int $code): void
636
    {
637
        if (isset($this->protocol)) {
638
            $this->protocol->writeExitCode($code);
639
        }
640
    }
641
642
    /**
643
     * Unref will be called whenever a JavaObject is not used,
644
     * see JavaProxy::__destruct() method.
645
     *
646
     * @param int $object object identifier
647
     */
648 107
    public function unref(?int $object): void
649
    {
650 107
        if (isset($this->protocol)) {
651 107
            $this->protocol->writeUnref($object);
652
        }
653 107
    }
654
655
    /**
656
     * @param ApplyArg $arg
657
     *
658
     * @throws Exception\JavaException
659
     * @throws Exception\RuntimeException
660
     */
661
    public function apply(ApplyArg $arg): void
662
    {
663
        $name = $arg->p;
664
        $object = $arg->v;
665
        $ob = ($object == null) ? $name : [&$object, $name];
666
        $isAsync = $this->isAsync;
667
        $methodCache = $this->methodCache;
668
        $currentArgumentsFormat = $this->currentArgumentsFormat;
669
        try {
670
            $res = $arg->getResult(true);
671
            if ((($object == null) && !function_exists($name)) || (!($object == null) && !method_exists($object, $name))) {
672
                throw new Exception\JavaException('java.lang.NoSuchMethodError', (string) $name);
673
            }
674
            $res = call_user_func($ob, $res);
675
            if (is_object($res) && (!($res instanceof JavaType))) {
676
                $msg = "Client failed to applyArg(), Object returned from '$name()' is not a Java object";
677
                $this->logger->warning("[soluble-japha] $msg (".__METHOD__.')');
678
                trigger_error($msg, E_USER_WARNING);
679
680
                $this->protocol->invokeBegin(0, 'makeClosure');
681
                $this->protocol->writeULong($this->globalRef->add($res));
682
                $this->protocol->invokeEnd();
683
                $res = $this->getResult();
684
            }
685
            $this->protocol->resultBegin();
686
            $this->writeArg($res);
687
            $this->protocol->resultEnd();
688
        } catch (Exception\JavaException $e) {
689
            $trace = $e->getTraceAsString();
690
            $this->protocol->resultBegin();
691
            $this->protocol->writeException($e->__java, $trace);
692
            $this->protocol->resultEnd();
693
        } catch (\Throwable $ex) {
694
            $msg = 'Unchecked exception detected in callback ('.$ex->__toString().')';
695
            $this->logger->error("[soluble-japha] $msg (".__METHOD__.')');
696
            trigger_error($msg, E_USER_WARNING);
697
            throw new Exception\RuntimeException($msg);
698
        }
699
        $this->isAsync = $isAsync;
700
        $this->methodCache = $methodCache;
701
        $this->currentArgumentsFormat = $currentArgumentsFormat;
702
    }
703
704
    /**
705
     * Cast an object to a certain type.
706
     *
707
     * @param JavaProxy $object
708
     * @param string    $type
709
     *
710
     * @return mixed
711
     *
712
     * @throws Exception\RuntimeException
713
     */
714 8
    public function cast(JavaProxy $object, $type)
715
    {
716 8
        $code = strtoupper($type[0]);
717 8
        switch ($code) {
718 8
            case 'S':
719
                return $this->invokeMethod(0, 'castToString', [$object]);
720 8
            case 'B':
721
                return $this->invokeMethod(0, 'castToBoolean', [$object]);
722 8
            case 'L':
723 8
            case 'I':
724
                return $this->invokeMethod(0, 'castToExact', [$object]);
725 8
            case 'D':
726 8
            case 'F':
727
                return $this->invokeMethod(0, 'castToInExact', [$object]);
728 8
            case 'N':
729
                return null;
730 8
            case 'A':
731 8
                return $this->invokeMethod(0, 'castToArray', [$object]);
732
            case 'O':
733
                return $object;
734
            default:
735
                throw new Exception\RuntimeException("Illegal type '$code' for casting");
736
        }
737
    }
738
739
    /**
740
     * Returns the jsr223 script context handle.
741
     *
742
     * Exposes the bindings from the ENGINE_SCOPE to PHP scripts. Values
743
     * set with engine.set("key", val) can be fetched from PHP with
744
     * java_context()->get("key"). Values set with
745
     * java_context()->put("key", java_closure($val)) can be fetched from
746
     * Java with engine.get("key"). The get/put methods are convenience shortcuts for getAttribute/setAttribute. Example:
747
     * <code>
748
     * engine.put("key1", 2);
749
     * engine.eval("<?php java_context()->put("key2", 1+(int)(string)java_context()->get('key1'));?>");
750
     * System.out.println(engine.get("key2"));
751
     *</code>
752
     *
753
     * 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:
754
     * <code>
755
     * function getShutdownHook() { return java("myJavaHelper")->getShutdownHook(); }
756
     * function call() { // called by init()
757
     *   ...
758
     *   // register shutdown hook
759
     *   java_context()->onShutdown(getShutdownHook());
760
     * }
761
     * java_context()->init(java_closure(null, null, java("java.util.concurrent.Callable")));
762
     * </code>
763
     *
764
     * It is possible to access implicit web objects (the session, the
765
     * application store etc.) from the context. Example:
766
     * <code>
767
     * $req = $ctx->getHttpServletRequest();
768
     * $res = $ctx->getHttpServletResponse();
769
     * $servlet = $ctx->getServlet();
770
     * $config = $ctx->getServletConfig();
771
     * $context = $ctx->getServletContext();
772
     * </code>
773
     *
774
     * The global bindings (shared with all available script engines) are
775
     * available from the GLOBAL_SCOPE, the script engine bindings are
776
     * available from the ENGINE_SCOPE. Example
777
     *
778
     * <code>
779
     * define ("ENGINE_SCOPE", 100);
780
     * define ("GLOBAL_SCOPE", 200);
781
     * echo java_context()->getBindings(ENGINE_SCOPE)->keySet();
782
     * echo java_context()->getBindings(GLOBAL_SCOPE)->keySet();
783
     * </code>
784
     *
785
     * Furthermore the context exposes the java continuation to PHP scripts.
786
     * Example which closes over the current environment and passes it back to java:
787
     * <code>
788
     * define ("ENGINE_SCOPE", 100);
789
     * $ctx = java_context();
790
     * if(java_is_false($ctx->call(java_closure()))) die "Script should be called from java";
791
     * </code>
792
     *
793
     * A second example which shows how to invoke PHP methods without the JSR 223 getInterface() and invokeMethod()
794
     * helper procedures. The Java code can fetch the current PHP continuation from the context using the key "php.java.bridge.PhpProcedure":
795
     * <code>
796
     * String s = "<?php class Runnable { function run() {...} };
797
     *            // example which captures an environment and
798
     *            // passes it as a continuation back to Java
799
     *            $Runnable = java('java.lang.Runnable');
800
     *            java_context()->call(java_closure(new Runnable(), null, $Runnable));
801
     *            ?>";
802
     * ScriptEngine e = new ScriptEngineManager().getEngineByName("php-invocable");
803
     * e.eval (s);
804
     * Thread t = new Thread((Runnable)e.get("php.java.bridge.PhpProcedure"));
805
     * t.join ();
806
     * ((Closeable)e).close ();
807
     * </code>
808
     *
809
     * @return Interfaces\JavaObject
810
     */
811 4
    public function getContext(): Interfaces\JavaObject
812
    {
813 4
        if ($this->cachedValues['getContext'] === null) {
814 1
            $this->cachedValues['getContext'] = $this->invokeMethod(0, 'getContext', []);
815
        }
816
817 4
        return $this->cachedValues['getContext'];
818
    }
819
820
    /**
821
     * Return a java (servlet) session handle.
822
     *
823
     * When getJavaSession() is called without
824
     * arguments, the session is shared with java.
825
     * Example:
826
     * <code>
827
     * $driver->getJavaSession()->put("key", new Java("java.lang.Object"));
828
     * [...]
829
     * </code>
830
     * The java components (jsp, servlets) can retrieve the value, for
831
     * example with:
832
     * <code>
833
     * getSession().getAttribute("key");
834
     * </code>
835
     *
836
     * When java_session() is called with a session name, the session
837
     * is not shared with java and no cookies are set. Example:
838
     * <code>
839
     * $driver->getJavaSession("myPublicApplicationStore")->put("key", "value");
840
     * </code>
841
     *
842
     * When java_session() is called with a second argument set to true,
843
     * a new session is allocated, the old session is destroyed if necessary.
844
     * Example:
845
     * <code>
846
     * $driver->getJavaSession(null, true)->put("key", "val");
847
     * </code>
848
     *
849
     * The optional third argument specifies the default lifetime of the session, it defaults to <code> session.gc_maxlifetime </code>. The value 0 means that the session never times out.
850
     *
851
     * The synchronized init() and onShutdown() callbacks from
852
     * java_context() and the JPersistenceAdapter (see
853
     * JPersistenceAdapter.php from the php_java_lib directory) may also
854
     * be useful to load a Java singleton object after the JavaBridge
855
     * library has been initialized, and to store it right before the web
856
     * context or the entire JVM will be terminated.
857
     *
858
     * @param array $args
859
     *
860
     * @return Interfaces\JavaObject
861
     */
862
    public function getSession(array $args = []): Interfaces\JavaObject
863
    {
864
        if (!isset($args[0])) {
865
            $args[0] = null;
866
        }
867
868
        if (!isset($args[1])) {
869
            $args[1] = 0;
870
        } // ISession.SESSION_GET_OR_CREATE
871
        elseif ($args[1] === true) {
872
            $args[1] = 1;
873
        } // ISession.SESSION_CREATE_NEW
874
        else {
875
            $args[1] = 2;
876
        } // ISession.SESSION_GET
877
878
        if (!isset($args[2])) {
879
            $args[2] = HelperFunctions::java_get_session_lifetime();
880
        }
881
882
        return $this->invokeMethod(0, 'getSession', $args);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->invokeMeth...0, 'getSession', $args) returns the type Soluble\Japha\Bridge\Driver\Pjb62\JavaType which is incompatible with the type-hinted return Soluble\Japha\Interfaces\JavaObject.
Loading history...
883
    }
884
885
    /**
886
     * @return string
887
     */
888 1
    public function getServerName(): string
889
    {
890 1
        if ($this->cachedValues['getServerName'] === null) {
891 1
            $this->cachedValues['getServerName'] = $this->protocol->getServerName();
892
        }
893
894 1
        return $this->cachedValues['getServerName'];
895
    }
896
897
    /**
898
     * Return client parameters.
899
     *
900
     * @return ArrayObject
901
     */
902
    public function getParams(): \ArrayObject
903
    {
904
        return $this->params;
905
    }
906
907
    /**
908
     * Return client parameter by name.
909
     *
910
     * @param string $param
911
     *
912
     * @return mixed
913
     */
914 97
    public function getParam($param)
915
    {
916 97
        return $this->params[$param];
917
    }
918
}
919