AbstractContainerThread::main()   F
last analyzed

Complexity

Conditions 13
Paths 384

Size

Total Lines 158
Code Lines 69

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 182

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 13
eloc 69
c 2
b 0
f 0
nc 384
nop 0
dl 0
loc 158
ccs 0
cts 78
cp 0
crap 182
rs 3.463

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
/**
4
 * \AppserverIo\Appserver\Core\AbstractContainerThread
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    Tim Wagner <[email protected]>
15
 * @author    Johann Zelger <[email protected]>
16
 * @author    Bernhard Wick <[email protected]>
17
 * @copyright 2015 TechDivision GmbH <[email protected]>
18
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
 * @link      https://github.com/appserver-io/appserver
20
 * @link      http://www.appserver.io
21
 */
22
23
namespace AppserverIo\Appserver\Core;
24
25
use AppserverIo\Logger\LoggerUtils;
26
use AppserverIo\Storage\GenericStackable;
27
use AppserverIo\Description\Api\Node\ParamNode;
28
use AppserverIo\Server\Dictionaries\ServerStateKeys;
29
use AppserverIo\Psr\Application\ApplicationInterface;
30
use AppserverIo\Psr\ApplicationServer\ContainerInterface;
31
use AppserverIo\Psr\Naming\NamingDirectoryInterface;
32
use AppserverIo\Psr\ApplicationServer\ContextInterface;
33
use AppserverIo\Psr\ApplicationServer\Configuration\ContainerConfigurationInterface;
34
use AppserverIo\Appserver\Core\Api\Node\ServerNodeInterface;
35
use AppserverIo\Appserver\Core\Utilities\ContainerStateKeys;
36
37
/**
38
 * Abstract container implementation.
39
 *
40
 * @author    Tim Wagner <[email protected]>
41
 * @author    Johann Zelger <[email protected]>
42
 * @author    Bernhard Wick <[email protected]>
43
 * @copyright 2015 TechDivision GmbH <[email protected]>
44
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
45
 * @link      https://github.com/appserver-io/appserver
46
 * @link      http://www.appserver.io
47
 *
48
 * @property \AppserverIo\Psr\Naming\NamingDirectoryInterface                                 $namingDirectory Naming directory used for binding various information to
49
 * @property \AppserverIo\Appserver\Core\Api\AppService                                       $service         The app service used to bind applications to the configuration
50
 * @property \AppserverIo\Psr\ApplicationServer\Configuration\ContainerConfigurationInterface $containerNode   The container node information
51
 * @property \AppserverIo\Storage\GenericStackable                                            $applications    The initialized applications
52
 * @property \AppserverIo\Appserver\Core\Utilities\ContainerStateKeys                         $containerState  The actual container state
53
 * @property string                                                                           $runlevel        The runlevel the container has been started in
54
 */
55
abstract class AbstractContainerThread extends AbstractContextThread implements ContainerInterface
56
{
57
58
    /**
59
     * The time we wait after each loop.
60
     *
61
     * @var integer
62
     */
63
    const TIME_TO_LIVE = 1;
64
65
    /**
66
     * Initializes the container with the initial context, the unique container ID
67
     * and the deployed applications.
68
     *
69
     * @param \AppserverIo\Psr\ApplicationServer\ContextInterface                              $initialContext  The initial context
70
     * @param \AppserverIo\Psr\Naming\NamingDirectoryInterface                                 $namingDirectory The naming directory
71
     * @param \AppserverIo\Psr\ApplicationServer\Configuration\ContainerConfigurationInterface $containerNode   The container node
72
     * @param string                                                                           $runlevel        The runlevel the container has been started in
73
     */
74 2
    public function __construct(
75
        ContextInterface $initialContext,
76
        NamingDirectoryInterface $namingDirectory,
77
        ContainerConfigurationInterface $containerNode,
78
        $runlevel
79
    ) {
80 2
        $this->initialContext = $initialContext;
81 2
        $this->namingDirectory = $namingDirectory;
82 2
        $this->containerNode = $containerNode;
83 2
        $this->runlevel = $runlevel;
84 2
        $this->containerState = ContainerStateKeys::get(ContainerStateKeys::WAITING_FOR_INITIALIZATION);
85 2
    }
86
87
    /**
88
     * Returns the unique container name from the configuration.
89
     *
90
     * @return string The unique container name
91
     * @see \AppserverIo\Psr\ApplicationServer\ContainerInterface::getName()
92
     */
93
    public function getName()
94
    {
95
        return $this->getContainerNode()->getName();
96
    }
97
98
    /**
99
     * Returns the runlevel the container has been started in.
100
     *
101
     * @return string The runlevel
102
     */
103
    public function getRunlevel()
104
    {
105
        return $this->runlevel;
106
    }
107
108
    /**
109
     * Return's the prepared server node configuration.
110
     *
111
     * @param \AppserverIo\Appserver\Core\Api\Node\ServerNodeInterface $serverNode The server node
112
     *
113
     * @return \AppserverIo\Appserver\Core\ServerNodeConfiguration The server node configuration
114
     */
115
    public function getServerNodeConfiguration(ServerNodeInterface $serverNode)
116
    {
117
118
        // query whether a server signature (software) has been configured
119
        if ($serverNode->getParam('software') == null) {
120
            $serverNode->setParam('software', ParamNode::TYPE_STRING, $this->getService()->getServerSignature());
121
        }
122
123
        // add the server node configuration
124
        return new ServerNodeConfiguration($serverNode);
125
    }
126
127
    /**
128
     * Run the containers logic
129
     *
130
     * @return void
131
     */
132
    public function main()
133
    {
134
135
        // register the default autoloader
136
        require SERVER_AUTOLOADER;
137
138
        // initialize the container state
139
        $this->containerState = ContainerStateKeys::get(ContainerStateKeys::WAITING_FOR_INITIALIZATION);
140
141
        // create a new API app service instance
142
        $this->service = $this->newService('AppserverIo\Appserver\Core\Api\AppService');
143
144
        // initialize the container for the configured class laoders
145
        $classLoaders = new GenericStackable();
146
147
        // register the configured class loaders
148
        $this->registerClassLoaders($classLoaders);
149
150
        // register shutdown handler
151
        register_shutdown_function(array(&$this, "shutdown"));
152
153
        // query whether the container's directories exists and are readable
154
        $this->validateDirectories();
155
156
        // initialize the naming directory with the environment data
157
        $this->namingDirectory->createSubdirectory(sprintf('php:env/%s', $this->getName()));
158
        $this->namingDirectory->createSubdirectory(sprintf('php:global/%s', $this->getName()));
159
        $this->namingDirectory->createSubdirectory(sprintf('php:global/log/%s', $this->getName()));
160
        $this->namingDirectory->bind(sprintf('php:env/%s/appBase', $this->getName()), $this->getAppBase());
0 ignored issues
show
Bug introduced by
$this->getAppBase() of type string is incompatible with the type object expected by parameter $value of AppserverIo\Psr\Naming\N...ectoryInterface::bind(). ( Ignorable by Annotation )

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

160
        $this->namingDirectory->bind(sprintf('php:env/%s/appBase', $this->getName()), /** @scrutinizer ignore-type */ $this->getAppBase());
Loading history...
161
        $this->namingDirectory->bind(sprintf('php:global/%s/runlevel', $this->getName()), $this->getRunlevel());
162
163
        // initialize the container state
164
        $this->containerState = ContainerStateKeys::get(ContainerStateKeys::INITIALIZATION_SUCCESSFUL);
165
166
        // initialize instance that contains the applications
167
        $this->applications = new GenericStackable();
168
169
        // initialize the profile logger and the thread context
170
        if ($profileLogger = $this->getInitialContext()->getLogger(LoggerUtils::PROFILE)) {
171
            $profileLogger->appendThreadContext($this->getContainerNode()->getName());
0 ignored issues
show
Bug introduced by
The method appendThreadContext() does not exist on Psr\Log\LoggerInterface. It seems like you code against a sub-type of Psr\Log\LoggerInterface such as AppserverIo\Logger\ThreadSafeLoggerInterface or Psr\Log\Test\TestLogger. ( Ignorable by Annotation )

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

171
            $profileLogger->/** @scrutinizer ignore-call */ 
172
                            appendThreadContext($this->getContainerNode()->getName());
Loading history...
172
        }
173
174
        // initialize the array for the server configurations
175
        $serverConfigurations = array();
176
177
        // load the server configurations and query whether a server signatures has been set
178
        /** @var \AppserverIo\Appserver\Core\Api\Node\ServerNodeInterface $serverNode */
179
        foreach ($this->getContainerNode()->getServers() as $serverNode) {
180
            $serverConfigurations[] = $this->getServerNodeConfiguration($serverNode);
181
        }
182
183
        // init upstreams
184
        $upstreams = array();
185
        if ($this->getContainerNode()->getUpstreams()) {
186
            $upstreams = $this->getContainerNode()->getUpstreams();
187
            foreach ($this->getContainerNode()->getUpstreams() as $upstreamNode) {
188
                // get upstream type
189
                $upstreamType = $upstreamNode->getType();
190
                // init upstream instance
191
                $upstream = new $upstreamType();
192
                // init upstream servers
193
                $servers = array();
194
                // get upstream servers from upstream
195
                foreach ($upstreamNode->getUpstreamServers() as $upstreamServerNode) {
196
                    $upstreamServerType = $upstreamServerNode->getType();
197
                    $upstreamServerParams = $upstreamServerNode->getParamsAsArray();
198
                    $servers[$upstreamServerNode->getName()] = new $upstreamServerType($upstreamServerParams);
199
                }
200
                // inject server instances to upstream
201
                $upstream->injectServers($servers);
202
                // set upstream by name
203
                $upstreams[$upstreamNode->getName()] = $upstream;
204
            }
205
        }
206
207
        // init server array
208
        $this->servers = new GenericStackable();
0 ignored issues
show
Bug Best Practice introduced by
The property servers does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
209
210
        // start servers by given configurations
211
        /** @var \AppserverIo\Server\Interfaces\ServerConfigurationInterface $serverConfig */
212
        foreach ($serverConfigurations as $serverConfig) {
213
            // get type definitions
214
            $serverType = $serverConfig->getType();
215
            $serverContextType = $serverConfig->getServerContextType();
216
217
            // create a new instance server context
218
            /** @var \AppserverIo\Server\Interfaces\ServerContextInterface $serverContext */
219
            $serverContext = new $serverContextType();
220
221
            // inject container to be available in specific mods etc. and initialize the module
222
            $serverContext->injectContainer($this);
223
224
            // init server context by config
225
            $serverContext->init($serverConfig);
226
227
            // inject upstreams
228
            $serverContext->injectUpstreams($upstreams);
229
230
            // inject loggers
231
            $serverContext->injectLoggers($this->getInitialContext()->getLoggers());
0 ignored issues
show
Bug introduced by
The method getLoggers() does not exist on AppserverIo\Psr\ApplicationServer\ContextInterface. Did you maybe mean getLogger()? ( Ignorable by Annotation )

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

231
            $serverContext->injectLoggers($this->getInitialContext()->/** @scrutinizer ignore-call */ getLoggers());

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...
232
233
            // create the server (which should start it automatically)
234
            /** @var \AppserverIo\Server\Interfaces\ServerInterface $server */
235
            $server = new $serverType($serverContext);
236
            // collect the servers we started
237
            $this->servers[$serverConfig->getName()] = $server;
238
        }
239
240
        // wait for all servers to be started
241
        $waitForServers = true;
242
        while ($waitForServers === true) {
243
            // iterate over all servers to check the state
244
            foreach ($this->servers as $server) {
245
                if ($server->serverState === ServerStateKeys::WORKERS_INITIALIZED) {
246
                    $waitForServers = false;
247
                } else {
248
                    $waitForServers = true;
249
                }
250
            }
251
            usleep(10000);
252
        }
253
254
        // the container has successfully been initialized
255
        $this->synchronized(function ($self) {
256
            $self->containerState = ContainerStateKeys::get(ContainerStateKeys::SERVERS_STARTED_SUCCESSFUL);
257
        }, $this);
258
259
        // initialize the flag to keep the application running
260
        $keepRunning = true;
261
262
        // wait till container will be shutdown
263
        while ($keepRunning) {
264
            // query whether we've a profile logger, log resource usage
265
            if ($profileLogger) {
266
                $profileLogger->debug(sprintf('Container %s still waiting for shutdown', $this->getContainerNode()->getName()));
267
            }
268
269
            // wait a second to lower system load
270
            $keepRunning = $this->synchronized(function ($self) {
271
                $self->wait(1000000 * AbstractContainerThread::TIME_TO_LIVE);
272
                return $self->containerState->equals(ContainerStateKeys::get(ContainerStateKeys::SERVERS_STARTED_SUCCESSFUL));
273
            }, $this);
274
        }
275
276
        // we need to stop all servers before we can shutdown the container
277
        /** @var \AppserverIo\Server\Interfaces\ServerInterface $server */
278
        foreach ($this->servers as $server) {
279
            $server->stop();
280
        }
281
282
        // mark the container as successfully shutdown
283
        $this->synchronized(function ($self) {
284
            $self->containerState = ContainerStateKeys::get(ContainerStateKeys::SHUTDOWN);
285
        }, $this);
286
287
        // send log message that the container has been shutdown
288
        $this->getInitialContext()->getSystemLogger()->info(
289
            sprintf('Successfully shutdown container %s', $this->getContainerNode()->getName())
290
        );
291
    }
292
293
    /**
294
     * Returns the containers naming directory.
295
     *
296
     * @return \AppserverIo\Psr\Naming\NamingDirectoryInterface The containers naming directory
297
     */
298
    public function getNamingDirectory()
299
    {
300
        return $this->namingDirectory;
301
    }
302
303
    /**
304
     * Returns the deployed servers.
305
     *
306
     * @return \AppserverIo\Storage\GenericStackable The servers
307
     */
308
    public function getServers()
309
    {
310
        return $this->servers;
311
    }
312
313
    /**
314
     * Returns the sever instance with the passed name.
315
     *
316
     * @param string $name The name of the server to return
317
     *
318
     * @return \AppserverIo\Server\Interfaces\ServerInterface The server instance
319
     */
320
    public function getServer($name)
321
    {
322
        if (isset($this->servers[$name])) {
323
            return $this->servers[$name];
324
        }
325
    }
326
327
    /**
328
     * Returns the deployed applications.
329
     *
330
     * @return \AppserverIo\Storage\GenericStackable The applications
331
     */
332
    public function getApplications()
333
    {
334
        return $this->applications;
335
    }
336
337
    /**
338
     * Returns the application instance with the passed name.
339
     *
340
     * @param string $name The name of the application to return
341
     *
342
     * @return \AppserverIo\Psr\Application\ApplicationInterface The application instance
343
     */
344
    public function getApplication($name)
345
    {
346
        if (isset($this->applications[$name])) {
347
            return $this->applications[$name];
348
        }
349
    }
350
351
    /**
352
     * Returns the containers configuration node.
353
     *
354
     * @return \AppserverIo\Appserver\Core\Api\Node\ContainerNode The configuration node
355
     */
356 1
    public function getContainerNode()
357
    {
358 1
        return $this->containerNode;
359
    }
360
361
    /**
362
     * Returns the service instance we need to handle system configuration tasks.
363
     *
364
     * @return \AppserverIo\Appserver\Core\Api\AppService The service instance we need
365
     */
366
    public function getService()
367
    {
368
        return $this->service;
369
    }
370
371
    /**
372
     * Returns the initial context instance.
373
     *
374
     * @return \AppserverIo\Psr\ApplicationServer\ContextInterface The initial context instance
375
     * @see \AppserverIo\Psr\ApplicationServer\ContainerInterface::getInitialContext()
376
     */
377 2
    public function getInitialContext()
378
    {
379 2
        return $this->initialContext;
380
    }
381
382
    /**
383
     * (non-PHPdoc)
384
     *
385
     * @param string $className The API service class name to return the instance for
386
     *
387
     * @return \AppserverIo\Psr\ApplicationServer\ServiceInterface The service instance
388
     * @see \AppserverIo\Appserver\Core\InitialContext::newService()
389
     */
390
    public function newService($className)
391
    {
392
        return $this->getInitialContext()->newService($className);
393
    }
394
395
    /**
396
     * (non-PHPdoc)
397
     *
398
     * @param string $className The fully qualified class name to return the instance for
399
     * @param array  $args      Arguments to pass to the constructor of the instance
400
     *
401
     * @return object The instance itself
402
     * @see \AppserverIo\Appserver\Core\InitialContext::newInstance()
403
     */
404 2
    public function newInstance($className, array $args = array())
405
    {
406 2
        return $this->getInitialContext()->newInstance($className, $args);
407
    }
408
409
    /**
410
     * Returns the deployment interface for the container for
411
     * this container thread.
412
     *
413
     * @return \AppserverIo\Psr\Deployment\DeploymentInterface The deployment instance for this container thread
414
     */
415 1
    public function getDeployment()
416
    {
417 1
        return $this->newInstance($this->getContainerNode()->getDeployment()->getType());
418
    }
419
420
    /**
421
     * (non-PHPdoc)
422
     *
423
     * @param string|null $directoryToAppend Append this directory to the base directory before returning it
424
     *
425
     * @return string The base directory
426
     * @see \AppserverIo\Appserver\Core\Api\ContainerService::getBaseDirectory()
427
     */
428
    public function getBaseDirectory($directoryToAppend = null)
429
    {
430
        return $this->getService()->getBaseDirectory($directoryToAppend);
431
    }
432
433
    /**
434
     * (non-PHPdoc)
435
     *
436
     * @return string The application base directory for this container
437
     * @see \AppserverIo\Appserver\Core\Api\ContainerService::getAppBase()
438
     */
439
    public function getAppBase()
440
    {
441
        return $this->getService()->getWebappsDir($this->getContainerNode());
442
    }
443
444
    /**
445
     * Returns the servers tmp directory, append with the passed directory.
446
     *
447
     * @param string|null $directoryToAppend The directory to append
448
     *
449
     * @return string
450
     */
451
    public function getTmpDir($directoryToAppend = null)
452
    {
453
        return $this->getService()->getTmpDir($this->getContainerNode(), $directoryToAppend);
454
    }
455
456
    /**
457
     * Connects the passed application to the system configuration.
458
     *
459
     * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application to be prepared
460
     *
461
     * @return void
462
     */
463
    public function addApplicationToSystemConfiguration(ApplicationInterface $application)
464
    {
465
466
        // try to load the API app service instance
467
        $appNode = $this->getService()->loadByWebappPath($application->getWebappPath());
468
469
        // check if the application has already been attached to the container
470
        if ($appNode == null) {
471
            $this->getService()->newFromApplication($application);
472
        }
473
474
        // connect the application to the container
475
        $application->connect();
476
    }
477
478
    /**
479
     * Append the deployed application to the deployment instance
480
     * and registers it in the system configuration.
481
     *
482
     * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application to append
483
     *
484
     * @return void
485
     */
486
    public function addApplication(ApplicationInterface $application)
487
    {
488
489
        // register the application in this instance
490
        $this->applications[$application->getName()] = $application;
491
492
        // adds the application to the system configuration
493
        $this->addApplicationToSystemConfiguration($application);
494
    }
495
496
    /**
497
     * Stops the container instance.
498
     *
499
     * @return void
500
     */
501
    public function stop()
502
    {
503
504
        // start container shutdown
505
        $this->synchronized(function ($self) {
506
            $self->containerState = ContainerStateKeys::get(ContainerStateKeys::HALT);
507
        }, $this);
508
509
        do {
510
            // wait for 0.5 seconds
511
            usleep(500000);
512
513
            // log a message that we'll wait till application has been shutdown
514
            $this->getInitialContext()->getSystemLogger()->info(
515
                sprintf('Wait for container %s to be shutdown', $this->getContainerNode()->getName())
516
            );
517
518
            // query whether application state key is SHUTDOWN or not
519
            $waitForShutdown = $this->synchronized(function ($self) {
520
                return $self->containerState->notEquals(ContainerStateKeys::get(ContainerStateKeys::SHUTDOWN));
521
            }, $this);
522
523
        } while ($waitForShutdown);
524
    }
525
526
    /**
527
     * Returns boolean wheather the servers has been started yet or not
528
     *
529
     * @return boolean
530
     */
531
    public function hasServersStarted()
532
    {
533
        return $this->containerState->equals(ContainerStateKeys::get(ContainerStateKeys::SERVERS_STARTED_SUCCESSFUL));
534
    }
535
536
    /**
537
     * Returns TRUE if application provisioning for the container is enabled, else FALSE.
538
     *
539
     * @return boolean TRUE if application provisioning is enabled, else FALSE
540
     */
541
    public function hasProvisioningEnabled()
542
    {
543
        return $this->getContainerNode()->getProvisioning();
544
    }
545
546
    /**
547
     * Does shutdown logic for request handler if something went wrong and
548
     * produces a fatal error for example.
549
     *
550
     * @return void
551
     */
552
    public function shutdown()
553
    {
554
        // check if there was a fatal error caused shutdown
555
        if ($lastError = error_get_last()) {
556
            // initialize type + message
557
            $type = 0;
558
            $message = '';
559
            // extract the last error values
560
            extract($lastError);
561
            // query whether we've a fatal/user error
562
            if ($type === E_ERROR || $type === E_USER_ERROR) {
563
                $this->getInitialContext()->getSystemLogger()->critical($message);
564
            }
565
        }
566
    }
567
568
    /**
569
     * Validates that the container's application and temporary directory is available.
570
     *
571
     * @return void
572
     */
573
    protected function validateDirectories()
574
    {
575
576
        // query whether the container's application directory is available and readable
577
        $appBase = $this->getAppBase();
578
        if (!is_dir($appBase) || !is_readable($appBase)) {
579
            $this->getInitialContext()->getSystemLogger()->critical(
580
                sprintf(
581
                    'Base directory (appBase) %s of container %s is no directory or not readable, can\'t deploy applications',
582
                    $appBase,
583
                    $this->getName()
584
                )
585
            );
586
        }
587
588
        // query whether the container's temporary directory is available and readable
589
        $tmpDir = $this->getTmpDir();
590
        if (!is_dir($tmpDir) || !is_readable($tmpDir)) {
591
            $this->getInitialContext()->getSystemLogger()->critical(
592
                sprintf(
593
                    'Temporary directory (tmpDir) %s of container %s is no directory or not readable!',
594
                    $tmpDir,
595
                    $this->getName()
596
                )
597
            );
598
        }
599
    }
600
601
    /**
602
     * Register's the class loaders configured for this container.
603
     *
604
     * @param \AppserverIo\Storage\GenericStackable $classLoaders The container for the class loader instances
605
     *
606
     * @return void
607
     */
608
    protected function registerClassLoaders(GenericStackable $classLoaders)
609
    {
610
611
        // intialize the additional container class loaders
612
        foreach ($this->getContainerNode()->getClassLoaders() as $classLoaderNode) {
613
            // initialize the storage for the include path
614
            $includePath = array();
615
616
            // load the application base directory
617
            $appBase = $this->getAppBase();
618
619
            // load the composer class loader for the configured directories
620
            foreach ($classLoaderNode->getDirectories() as $directory) {
621
                // we prepare the directories to include scripts AFTER registering (in application context)
622
                $includePath[] = $appBase . $directory->getNodeValue();
623
            }
624
625
            // load the class loader type
626
            $className = $classLoaderNode->getType();
627
628
            // initialize and register the class loader instance
629
            $classLoaders[$classLoaderNode->getName()] = new $className(new GenericStackable(), $includePath);
630
            $classLoaders[$classLoaderNode->getName()]->register(true, true);
631
        }
632
    }
633
}
634