BeanManager::postStartup()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 13
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 4
nc 3
nop 1
dl 0
loc 13
ccs 0
cts 6
cp 0
crap 20
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * \AppserverIo\Appserver\PersistenceContainer\BeanManager
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Bernhard Wick <[email protected]>
15
 * @author    Tim Wagner <[email protected]>
16
 * @copyright 2015 TechDivision GmbH <[email protected]>
17
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
18
 * @link      https://github.com/appserver-io/appserver
19
 * @link      http://www.appserver.io
20
 */
21
22
namespace AppserverIo\Appserver\PersistenceContainer;
23
24
use AppserverIo\Storage\GenericStackable;
25
use AppserverIo\Storage\StorageInterface;
26
use AppserverIo\Collections\CollectionInterface;
27
use AppserverIo\Lang\Reflection\AnnotationInterface;
28
use AppserverIo\RemoteMethodInvocation\RemoteMethodInterface;
29
use AppserverIo\Appserver\Core\Environment;
30
use AppserverIo\Appserver\Core\AbstractEpbManager;
31
use AppserverIo\Appserver\Core\Utilities\EnvironmentKeys;
32
use AppserverIo\Psr\Servlet\SessionUtils;
33
use AppserverIo\Psr\Di\ObjectManagerInterface;
34
use AppserverIo\Psr\Deployment\DescriptorInterface;
35
use AppserverIo\Psr\Application\ApplicationInterface;
36
use AppserverIo\Psr\EnterpriseBeans\BeanContextInterface;
37
use AppserverIo\Psr\EnterpriseBeans\ResourceLocatorInterface;
38
use AppserverIo\Psr\EnterpriseBeans\InvalidBeanTypeException;
39
use AppserverIo\Psr\EnterpriseBeans\Description\BeanDescriptorInterface;
40
use AppserverIo\Psr\EnterpriseBeans\Description\SessionBeanDescriptorInterface;
41
use AppserverIo\Psr\EnterpriseBeans\Description\SingletonSessionBeanDescriptorInterface;
42
use AppserverIo\Psr\EnterpriseBeans\Description\StatefulSessionBeanDescriptorInterface;
43
use AppserverIo\Psr\EnterpriseBeans\Description\StatelessSessionBeanDescriptorInterface;
44
use AppserverIo\Psr\EnterpriseBeans\Description\MessageDrivenBeanDescriptorInterface;
45
use AppserverIo\Appserver\Application\Interfaces\ManagerSettingsInterface;
46
use AppserverIo\Appserver\Application\Interfaces\ManagerSettingsAwareInterface;
47
use AppserverIo\Appserver\PersistenceContainer\Utils\SessionBeanUtil;
48
use AppserverIo\Appserver\PersistenceContainer\Tasks\StartupBeanTask;
49
use AppserverIo\Appserver\PersistenceContainer\GarbageCollectors\StandardGarbageCollector;
50
use AppserverIo\Appserver\PersistenceContainer\RemoteMethodInvocation\ProxyGeneratorInterface;
51
use AppserverIo\Appserver\PersistenceContainer\GarbageCollectors\StartupBeanTaskGarbageCollector;
52
53
/**
54
 * The bean manager handles the message and session beans registered for the application.
55
 *
56
 * @author    Bernhard Wick <[email protected]>
57
 * @author    Tim Wagner <[email protected]>
58
 * @copyright 2015 TechDivision GmbH <[email protected]>
59
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
60
 * @link      https://github.com/appserver-io/appserver
61
 * @link      http://www.appserver.io
62
 *
63
 * @property array                                                                                         $requestContext                  The request context to cache the beans
64
 * @property \AppserverIo\Psr\EnterpriseBeans\ResourceLocatorInterface                                     $resourceLocator                 The resource locator
65
 * @property \AppserverIo\Storage\StorageInterface                                                         $statefulSessionBeans            The storage for the stateful session beans
66
 * @property \AppserverIo\Storage\StorageInterface                                                         $singletonSessionBeans           The storage for the singleton session beans
67
 * @property \AppserverIo\Appserver\PersistenceContainer\BeanManagerSettingsInterface                      $managerSettings                 Settings for the bean manager
68
 * @property \AppserverIo\Appserver\PersistenceContainer\StatefulSessionBeanMapFactory                     $statefulSessionBeanMapFactory   The factory instance
69
 * @property \AppserverIo\Appserver\PersistenceContainer\ObjectFactoryInterface                            $objectFactory                   The object factory instance
70
 * @property \AppserverIo\Appserver\PersistenceContainer\RemoteMethodInvocation\ProxyGeneratorInterface    $remoteProxyGenerator            The remote proxy generator
71
 * @property \AppserverIo\Storage\GenericStackable                                                         $startupBeanTasks                The storage with manager's startup bean tasks
72
 * @property \AppserverIo\Appserver\PersistenceContainer\GarbageCollectors\StandardGarbageCollector        $garbageCollector                The standard garbage collection for the SFSBs
73
 * @property \AppserverIo\Appserver\PersistenceContainer\GarbageCollectors\StartupBeanTaskGarbageCollector $startupBeanTaskGarbageCollector The garbage collector for the startup bean tasks
74
 */
75
class BeanManager extends AbstractEpbManager implements BeanContextInterface, ManagerSettingsAwareInterface
76
{
77
78
    /**
79
     * Injects the request context to cache the beans.
80
     *
81
     * @param array $requestContext The request context
82
     *
83
     * @return void
84
     */
85
    public function injectRequestContext(array $requestContext)
86
    {
87
        $this->requestContext = $requestContext;
88
    }
89
90
    /**
91
     * Injects the resource locator to lookup the requested queue.
92
     *
93
     * @param \AppserverIo\Psr\EnterpriseBeans\ResourceLocatorInterface $resourceLocator The resource locator
94
     *
95
     * @return void
96
     */
97
    public function injectResourceLocator(ResourceLocatorInterface $resourceLocator)
98
    {
99
        $this->resourceLocator = $resourceLocator;
100
    }
101
102
    /**
103
     * Injects the storage for the stateful session beans.
104
     *
105
     * @param \AppserverIo\Storage\StorageInterface $statefulSessionBeans The storage for the stateful session beans
106
     *
107
     * @return void
108
     */
109
    public function injectStatefulSessionBeans($statefulSessionBeans)
110
    {
111
        $this->statefulSessionBeans = $statefulSessionBeans;
112
    }
113
114
    /**
115
     * Injects the storage for the singleton session beans.
116
     *
117
     * @param \AppserverIo\Storage\StorageInterface $singletonSessionBeans The storage for the singleton session beans
118
     *
119
     * @return void
120
     */
121
    public function injectSingletonSessionBeans(StorageInterface $singletonSessionBeans)
122
    {
123
        $this->singletonSessionBeans = $singletonSessionBeans;
124
    }
125
126
    /**
127
     * Injects the bean manager settings.
128
     *
129
     * @param \AppserverIo\Appserver\PersistenceContainer\BeanManagerSettingsInterface $managerSettings The bean manager settings
130
     *
131
     * @return void
132
     */
133
    public function injectManagerSettings(ManagerSettingsInterface $managerSettings)
134
    {
135
        $this->managerSettings = $managerSettings;
0 ignored issues
show
Documentation Bug introduced by
$managerSettings is of type AppserverIo\Appserver\Ap...anagerSettingsInterface, but the property $managerSettings was declared to be of type AppserverIo\Appserver\Pe...anagerSettingsInterface. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
136
    }
137
138
    /**
139
     * Injects the object factory instance.
140
     *
141
     * @param \AppserverIo\Appserver\PersistenceContainer\ObjectFactoryInterface $objectFactory The object factory instance
142
     *
143
     * @return void
144
     */
145
    public function injectObjectFactory(ObjectFactoryInterface $objectFactory)
146
    {
147
        $this->objectFactory = $objectFactory;
148
    }
149
150
    /**
151
     * Injects the garbage collector.
152
     *
153
     * @param \AppserverIo\Appserver\PersistenceContainer\GarbageCollectors\StandardGarbageCollector $garbageCollector The garbage collector
154
     *
155
     * @return void
156
     */
157
    public function injectGarbageCollector(StandardGarbageCollector $garbageCollector)
158
    {
159
        $this->garbageCollector = $garbageCollector;
160
    }
161
162
    /**
163
     * Injects the startup bean task garbage collector.
164
     *
165
     * @param \AppserverIo\Appserver\PersistenceContainer\GarbageCollectors\StartupBeanTaskGarbageCollector $startupBeanTaskGarbageCollector The garbage collector
166
     *
167
     * @return void
168
     */
169
    public function injectStartupBeanTaskGarbageCollector(StartupBeanTaskGarbageCollector $startupBeanTaskGarbageCollector)
170
    {
171
        $this->startupBeanTaskGarbageCollector = $startupBeanTaskGarbageCollector;
172
    }
173
174
    /**
175
     * Injects the remote proxy generator.
176
     *
177
     * @param \AppserverIo\Appserver\PersistenceContainer\RemoteMethodInvocation\ProxyGeneratorInterface $remoteProxyGenerator The remote proxy generator
178
     *
179
     * @return void
180
     */
181
    public function injectRemoteProxyGenerator(ProxyGeneratorInterface $remoteProxyGenerator)
182
    {
183
        $this->remoteProxyGenerator = $remoteProxyGenerator;
184
    }
185
186
    /**
187
     * Injects the storage for the startup bean tasks.
188
     *
189
     * @param \AppserverIo\Storage\GenericStackable $startupBeanTasks The storage for the startup bean tasks
190
     *
191
     * @return void
192
     */
193
    public function injectStartupBeanTasks(GenericStackable $startupBeanTasks)
194
    {
195
        $this->startupBeanTasks = $startupBeanTasks;
196
    }
197
198
    /**
199
     * Lifecycle callback that'll be invoked after the application has been started.
200
     *
201
     * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application instance
202
     *
203
     * @return void
204
     * @see \AppserverIo\Psr\Application\ManagerInterface::postStartup()
205
     */
206
    public function postStartup(ApplicationInterface $application)
207
    {
208
209
        // load the object manager
210
        /** @var \AppserverIo\Psr\Di\ObjectManagerInterface $objectManager */
211
        $objectManager = $application->search(ObjectManagerInterface::IDENTIFIER);
212
213
        // register the beans found by annotations and the XML configuration
214
        /** \AppserverIo\Psr\Deployment\DescriptorInterface $objectDescriptor */
215
        foreach ($objectManager->getObjectDescriptors() as $descriptor) {
216
            // if we found a singleton session bean with a startup callback instanciate it
217
            if ($descriptor instanceof SingletonSessionBeanDescriptorInterface && $descriptor->isInitOnStartup()) {
218
                $this->startupBeanTasks[] = new StartupBeanTask($application, $descriptor);
219
            }
220
        }
221
    }
222
223
    /**
224
     * Has been automatically invoked by the container after the application
225
     * instance has been created.
226
     *
227
     * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application instance
228
     *
229
     * @return void
230
     * @see \AppserverIo\Psr\Application\ManagerInterface::initialize()
231
     */
232
    public function initialize(ApplicationInterface $application)
233
    {
234
235
        // add the application instance to the environment
236
        Environment::singleton()->setAttribute(EnvironmentKeys::APPLICATION, $application);
237
238
        // create s simulated request/session ID whereas session equals request ID
239
        Environment::singleton()->setAttribute(EnvironmentKeys::SESSION_ID, $sessionId = SessionUtils::generateRandomString());
240
        Environment::singleton()->setAttribute(EnvironmentKeys::REQUEST_ID, $sessionId);
241
242
        // finally register the beans
243
        $this->registerBeans($application);
244
    }
245
246
    /**
247
     * Registers the message beans at startup.
248
     *
249
     * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application instance
250
     *
251
     * @return void
252
     */
253
    public function registerBeans(ApplicationInterface $application)
254
    {
255
256
        // parse the object descriptors
257
        $this->parseObjectDescriptors();
258
259
        // load the object manager
260
        /** @var \AppserverIo\Psr\Di\ObjectManagerInterface $objectManager */
261
        $objectManager = $this->getApplication()->search(ObjectManagerInterface::IDENTIFIER);
262
263
        // register the beans found by annotations and the XML configuration
264
        /** \AppserverIo\Psr\Deployment\DescriptorInterface $objectDescriptor */
265
        foreach ($objectManager->getObjectDescriptors() as $descriptor) {
266
            // check if we've found a bean descriptor and register the bean
267
            if ($descriptor instanceof BeanDescriptorInterface) {
268
                $this->registerBean($descriptor);
269
            }
270
        }
271
    }
272
273
    /**
274
     * Register the bean described by the passed descriptor.
275
     *
276
     * @param \AppserverIo\Psr\EnterpriseBeans\Description\BeanDescriptorInterface $descriptor The bean descriptor
277
     *
278
     * @return void
279
     */
280
    public function registerBean(BeanDescriptorInterface $descriptor)
281
    {
282
283
        try {
284
            // load the application instance
285
            $application = $this->getApplication();
286
287
            // register the bean with the default name/short class name
288
            $application->getNamingDirectory()
0 ignored issues
show
Bug introduced by
The method getNamingDirectory() does not exist on AppserverIo\Psr\Application\ApplicationInterface. It seems like you code against a sub-type of AppserverIo\Psr\Application\ApplicationInterface such as AppserverIo\Appserver\Application\Application. ( Ignorable by Annotation )

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

288
            $application->/** @scrutinizer ignore-call */ 
289
                          getNamingDirectory()
Loading history...
289
                        ->bind(
290
                            sprintf('php:global/%s/%s', $application->getUniqueName(), $descriptor->getName()),
0 ignored issues
show
Bug introduced by
The method getUniqueName() does not exist on AppserverIo\Psr\Application\ApplicationInterface. It seems like you code against a sub-type of AppserverIo\Psr\Application\ApplicationInterface such as AppserverIo\Appserver\Application\Application. ( Ignorable by Annotation )

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

290
                            sprintf('php:global/%s/%s', $application->/** @scrutinizer ignore-call */ getUniqueName(), $descriptor->getName()),
Loading history...
291
                            array(&$this, 'lookup'),
292
                            array($descriptor->getName())
293
                        );
294
295
            // register's the bean's references
296
            $this->registerReferences($descriptor);
297
298
            // generate the remote proxy and register it in the naming directory
299
            $this->getRemoteProxyGenerator()->generate($descriptor);
300
301
        } catch (\Exception $e) {
302
            // log the exception
303
            $this->getApplication()->getInitialContext()->getSystemLogger()->critical($e->__toString());
0 ignored issues
show
Bug introduced by
The method getInitialContext() does not exist on AppserverIo\Psr\Application\ApplicationInterface. It seems like you code against a sub-type of AppserverIo\Psr\Application\ApplicationInterface such as AppserverIo\Appserver\Application\Application. ( Ignorable by Annotation )

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

303
            $this->getApplication()->/** @scrutinizer ignore-call */ getInitialContext()->getSystemLogger()->critical($e->__toString());
Loading history...
304
        }
305
    }
306
307
    /**
308
     * Creates a new new instance of the annotation type, defined in the passed reflection annotation.
309
     *
310
     * @param \AppserverIo\Lang\Reflection\AnnotationInterface $annotation The reflection annotation we want to create the instance for
311
     *
312
     * @return \AppserverIo\Lang\Reflection\AnnotationInterface The real annotation instance
313
     */
314
    public function newAnnotationInstance(AnnotationInterface $annotation)
315
    {
316
        return $this->getApplication()->search('ProviderInterface')->newAnnotationInstance($annotation);
317
    }
318
319
    /**
320
     * Return the resource locator instance.
321
     *
322
     * @return \AppserverIo\Psr\EnterpriseBeans\ResourceLocatorInterface The resource locator instance
323
     */
324
    public function getResourceLocator()
325
    {
326
        return $this->resourceLocator;
327
    }
328
329
    /**
330
     * Return the storage with the singleton session beans.
331
     *
332
     * @return \AppserverIo\Storage\StorageInterface The storage with the singleton session beans
333
     */
334
    public function getSingletonSessionBeans()
335
    {
336
        return $this->singletonSessionBeans;
337
    }
338
339
    /**
340
     * Return the storage with the stateful session beans.
341
     *
342
     * @return \AppserverIo\Storage\StorageInterface The storage with the stateful session beans
343
     */
344
    public function getStatefulSessionBeans()
345
    {
346
        return $this->statefulSessionBeans;
347
    }
348
349
    /**
350
     * Return's the bean manager settings.
351
     *
352
     * @return \AppserverIo\Appserver\PersistenceContainer\BeanManagerSettingsInterface The bean manager settings
353
     */
354
    public function getManagerSettings()
355
    {
356
        return $this->managerSettings;
357
    }
358
359
    /**
360
     * Returns the object factory instance.
361
     *
362
     * @return \AppserverIo\Appserver\PersistenceContainer\ObjectFactoryInterface The object factory instance
363
     */
364
    public function getObjectFactory()
365
    {
366
        return $this->objectFactory;
367
    }
368
369
    /**
370
     * Returns the garbage collector instance.
371
     *
372
     * @return \AppserverIo\Appserver\PersistenceContainer\GarbageCollectors\StandardGarbageCollector The garbage collector instance
373
     */
374
    public function getGarbageCollector()
375
    {
376
        return $this->garbageCollector;
377
    }
378
379
    /**
380
     * Returns the startup bean task garbage collector instance.
381
     *
382
     * @return \AppserverIo\Appserver\PersistenceContainer\GarbageCollectors\StartupBeanTaskGarbageCollector The garbage collector instance
383
     */
384
    public function getStartupBeanTaskGarbageCollector()
385
    {
386
        return $this->startupBeanTaskGarbageCollector;
387
    }
388
389
    /**
390
     * Return's the remote proxy generator instance.
391
     *
392
     * @return \AppserverIo\Appserver\PersistenceContainer\RemoteMethodInvocation\ProxyGeneratorInterface The remote proxy generator instance
393
     */
394
    public function getRemoteProxyGenerator()
395
    {
396
        return $this->remoteProxyGenerator;
397
    }
398
399
    /**
400
     * Return's the storage of the manager's post startup threads.
401
     *
402
     * @return \AppserverIo\Storage\GenericStackable The storage for the post startup threads
403
     */
404
    public function getStartupBeanTasks()
405
    {
406
        return $this->startupBeanTasks;
407
    }
408
409
    /**
410
     * Runs a lookup for the session bean with the passed class name and
411
     * session ID.
412
     *
413
     * If the passed class name is a session bean an instance
414
     * will be returned.
415
     *
416
     * @param string $className The name of the session bean's class
417
     * @param array  $args      The arguments passed to the session beans constructor
418
     *
419
     * @return object The requested bean instance
420
     */
421
    public function lookup($className, array $args = array())
422
    {
423
        return $this->getResourceLocator()->lookup($this, $className, $args);
424
    }
425
426
    /**
427
     * Retrieves the requested stateful session bean.
428
     *
429
     * @param string $sessionId The session-ID of the stateful session bean to retrieve
430
     * @param string $className The class name of the session bean to retrieve
431
     *
432
     * @return object|null The stateful session bean if available
433
     */
434
    public function lookupStatefulSessionBean($sessionId, $className)
435
    {
436
437
        // create a unique SFSB identifier
438
        $identifier = SessionBeanUtil::createIdentifier($sessionId, $className);
439
440
        // load the map with the SFSBs
441
        $sessionBeans = $this->getStatefulSessionBeans();
442
443
        // if the SFSB exists, return it
444
        if ($sessionBeans->exists($identifier)) {
0 ignored issues
show
Bug introduced by
The method exists() does not exist on AppserverIo\Storage\StorageInterface. ( Ignorable by Annotation )

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

444
        if ($sessionBeans->/** @scrutinizer ignore-call */ exists($identifier)) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
445
            return $sessionBeans->get($identifier);
446
        }
447
    }
448
449
    /**
450
     * Removes the stateful session bean with the passed session-ID and class name
451
     * from the bean manager.
452
     *
453
     * @param string $sessionId The session-ID of the stateful session bean to retrieve
454
     * @param string $className The class name of the session bean to retrieve
455
     *
456
     * @return void
457
     */
458
    public function removeStatefulSessionBean($sessionId, $className)
459
    {
460
461
        // create a unique SFSB identifier
462
        $identifier = SessionBeanUtil::createIdentifier($sessionId, $className);
463
464
        // load the map with the SFSBs
465
        $sessionBeans = $this->getStatefulSessionBeans();
466
467
        // query whether the SFSB with the passed identifier exists
468
        if ($sessionBeans->exists($identifier)) {
469
            $sessionBeans->remove($identifier, array($this, 'destroyBeanInstance'));
0 ignored issues
show
Unused Code introduced by
The call to AppserverIo\Storage\StorageInterface::remove() has too many arguments starting with array($this, 'destroyBeanInstance'). ( Ignorable by Annotation )

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

469
            $sessionBeans->/** @scrutinizer ignore-call */ 
470
                           remove($identifier, array($this, 'destroyBeanInstance'));

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
470
        }
471
    }
472
473
    /**
474
     * Returns a new instance of the SSB with the passed class name.
475
     *
476
     * @param string $className The fully qualified class name to return the instance for
477
     * @param array  $args      Arguments to pass to the constructor of the instance
478
     *
479
     * @return object The instance itself
480
     */
481
    public function newSingletonSessionBeanInstance($className, array $args = array())
482
    {
483
        return $this->getObjectFactory()->newInstance($className, $args);
0 ignored issues
show
Unused Code introduced by
The call to AppserverIo\Appserver\Pe...nterface::newInstance() has too many arguments starting with $args. ( Ignorable by Annotation )

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

483
        return $this->getObjectFactory()->/** @scrutinizer ignore-call */ newInstance($className, $args);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
484
    }
485
486
    /**
487
     * Retrieves the requested singleton session bean.
488
     *
489
     * @param string $className The class name of the session bean to retrieve
490
     *
491
     * @return object|null The singleton session bean if available
492
     */
493
    public function lookupSingletonSessionBean($className)
494
    {
495
        if ($this->getSingletonSessionBeans()->has($className) === true) {
496
            return $this->getSingletonSessionBeans()->get($className);
497
        }
498
    }
499
500
    /**
501
     * Invokes the bean method with a pre-destroy callback.
502
     *
503
     * @param object $instance The instance to invoke the method
504
     *
505
     * @return void
506
     */
507
    public function destroyBeanInstance($instance)
508
    {
509
510
        // load the object manager
511
        $objectManager = $this->getApplication()->search(ObjectManagerInterface::IDENTIFIER);
512
513
        // load the bean descriptor
514
        $descriptor = $objectManager->getObjectDescriptors()->get(get_class($instance));
515
516
        // invoke the pre-destroy callbacks if we've a session bean
517
        if ($descriptor instanceof SessionBeanDescriptorInterface) {
518
            foreach ($descriptor->getPreDestroyCallbacks() as $preDestroyCallback) {
519
                $instance->$preDestroyCallback();
520
            }
521
        }
522
    }
523
524
    /**
525
     * Invoke the passed remote method on the described session bean and return the result.
526
     *
527
     * @param \AppserverIo\RemoteMethodInvocation\RemoteMethodInterface $remoteMethod The remote method description
528
     * @param \AppserverIo\Collections\CollectionInterface              $sessions     The collection with the sessions
529
     *
530
     * @return mixed The result of the remote method invocation
531
     */
532
    public function invoke(RemoteMethodInterface $remoteMethod, CollectionInterface $sessions)
533
    {
534
535
        // prepare method name and parameters and invoke method
536
        $className  = $remoteMethod->getClassName();
537
        $methodName = $remoteMethod->getMethodName();
538
        $parameters = $remoteMethod->getParameters();
539
540
        // load the session ID from the environment
541
        $sessionId = Environment::singleton()->getAttribute(EnvironmentKeys::SESSION_ID);
542
543
        // load the application instance
544
        $application = $this->getApplication();
545
546
        // load a fresh bean instance and add it to the session container
547
        $instance = $this->lookup($className);
548
549
        // invoke the remote method call on the local instance
550
        $response = call_user_func_array(array($instance, $methodName), $parameters);
551
552
        // load the object manager
553
        $objectManager = $application->search(ObjectManagerInterface::IDENTIFIER);
554
555
        // load the bean descriptor
556
        $objectDescriptor = $objectManager->getObjectDescriptor($className);
557
558
        // initialize the flag to mark the instance to be re-attached
559
        $attach = true;
560
561
        // query if we've SFSB
562
        if ($objectDescriptor instanceof StatefulSessionBeanDescriptorInterface) {
563
            // remove the SFSB instance if a remove method has been called
564
            if ($objectDescriptor->isRemoveMethod($methodName)) {
565
                $this->removeStatefulSessionBean($sessionId, $objectDescriptor->getClassName());
566
                $attach = false;
567
            }
568
        }
569
570
        // re-attach the bean instance if necessary
571
        if ($attach === true) {
572
            $this->attach($objectDescriptor, $instance);
573
        }
574
575
        // return the remote method call result
576
        return $response;
577
    }
578
579
    /**
580
     * Attaches the passed bean, depending on it's type to the container.
581
     *
582
     * @param \AppserverIo\Psr\Deployment\DescriptorInterface $objectDescriptor The object descriptor for the passed instance
583
     * @param object                                          $instance         The bean instance to attach
584
     *
585
     * @return void
586
     * @throws \AppserverIo\Psr\EnterpriseBeans\InvalidBeanTypeException Is thrown if a invalid bean type has been detected
587
     */
588
    public function attach(DescriptorInterface $objectDescriptor, $instance)
589
    {
590
591
        // load the session ID from the environment
592
        $sessionId = Environment::singleton()->getAttribute(EnvironmentKeys::SESSION_ID);
593
594
        // query if we've stateful session bean
595
        if ($objectDescriptor instanceof StatefulSessionBeanDescriptorInterface) {
596
            // check if we've a session-ID available
597
            if ($sessionId == null) {
598
                throw new \Exception('Can\'t find a session-ID to attach stateful session bean');
599
            }
600
601
            // load the lifetime from the session bean settings
602
            $lifetime = $this->getManagerSettings()->getLifetime();
603
604
            // we've to check for pre-attach callbacks
605
            foreach ($objectDescriptor->getPreAttachCallbacks() as $preAttachCallback) {
606
                $instance->$preAttachCallback();
607
            }
608
609
            // create a unique SFSB identifier
610
            $identifier = SessionBeanUtil::createIdentifier($sessionId, $objectDescriptor->getName());
611
612
            // load the map with the SFSBs
613
            $sessionBeans = $this->getStatefulSessionBeans();
614
615
            // add the stateful session bean to the map
616
            $sessionBeans->add($identifier, $instance, $lifetime);
0 ignored issues
show
Bug introduced by
The method add() does not exist on AppserverIo\Storage\StorageInterface. ( Ignorable by Annotation )

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

616
            $sessionBeans->/** @scrutinizer ignore-call */ 
617
                           add($identifier, $instance, $lifetime);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
617
618
            // stop processing here
619
            return;
620
        }
621
622
        // query if we've stateless session or message bean
623
        if ($objectDescriptor instanceof StatelessSessionBeanDescriptorInterface ||
624
            $objectDescriptor instanceof MessageDrivenBeanDescriptorInterface) {
625
            // simply destroy the instance
626
            $this->destroyBeanInstance($instance);
627
628
            // stop processing here
629
            return;
630
        }
631
632
        // query if we've singleton session bean
633
        if ($objectDescriptor instanceof SingletonSessionBeanDescriptorInterface) {
634
            // we've to check for pre-attach callbacks
635
            foreach ($objectDescriptor->getPreAttachCallbacks() as $preAttachCallback) {
636
                $instance->$preAttachCallback();
637
            }
638
639
            // stop processing here
640
            return;
641
        }
642
643
        // we've an unknown bean type => throw an exception
644
        throw new InvalidBeanTypeException('Tried to attach invalid bean type');
645
    }
646
647
    /**
648
     * Returns the identifier for the bean manager instance.
649
     *
650
     * @return string
651
     * @see \AppserverIo\Psr\Application\ManagerInterface::getIdentifier()
652
     */
653
    public function getIdentifier()
654
    {
655
        return BeanContextInterface::IDENTIFIER;
656
    }
657
658
    /**
659
     * Shutdown the session manager instance.
660
     *
661
     * @return void
662
     * \AppserverIo\Psr\Application\ManagerInterface::stop()
663
     */
664
    public function stop()
665
    {
666
        $this->getGarbageCollector()->stop();
667
        $this->getStartupBeanTaskGarbageCollector()->stop();
668
        $this->getObjectFactory()->stop();
0 ignored issues
show
Bug introduced by
The method stop() does not exist on AppserverIo\Appserver\Pe...\ObjectFactoryInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to AppserverIo\Appserver\Pe...\ObjectFactoryInterface. ( Ignorable by Annotation )

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

668
        $this->getObjectFactory()->/** @scrutinizer ignore-call */ stop();
Loading history...
669
    }
670
}
671