Completed
Pull Request — master (#1105)
by Tim
42:55
created

ApplicationServer::doSwitchSetupMode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 2
dl 0
loc 9
ccs 0
cts 1
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * \AppserverIo\Appserver\Core\ApplicationServer
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
 * @copyright 2015 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/appserver-io/appserver
18
 * @link      http://www.appserver.io
19
 */
20
21
namespace AppserverIo\Appserver\Core;
22
23
use League\Event\Emitter;
24
use React\Socket\ConnectionInterface;
25
use AppserverIo\Logger\Logger;
26
use AppserverIo\Storage\GenericStackable;
27
use AppserverIo\Psr\Naming\NamingException;
28
use AppserverIo\Psr\Naming\NamingDirectoryInterface;
29
use AppserverIo\Appserver\Naming\Utils\NamingDirectoryKeys;
30
use AppserverIo\Appserver\Core\Commands\ModeCommand;
31
use AppserverIo\Appserver\Core\Commands\InitCommand;
32
use AppserverIo\Appserver\Core\Api\Node\BootstrapNode;
33
use AppserverIo\Appserver\Core\Utilities\Runlevels;
34
use AppserverIo\Appserver\Core\Listeners\ApplicationServerAwareListenerInterface;
35
use AppserverIo\Psr\ApplicationServer\ContextInterface;
36
use AppserverIo\Psr\ApplicationServer\ApplicationServerInterface;
37
use AppserverIo\Psr\ApplicationServer\Configuration\SystemConfigurationInterface;
38
39
/**
40
 * This is the main server class that starts the application server
41
 * and creates a separate thread for each container found in the
42
 * configuration file.
43
 *
44
 * @author    Tim Wagner <[email protected]>
45
 * @copyright 2015 TechDivision GmbH <[email protected]>
46
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
47
 * @link      https://github.com/appserver-io/appserver
48
 * @link      http://www.appserver.io
49
 */
50
class ApplicationServer extends \Thread implements ApplicationServerInterface
51
{
52
53
    /**
54
     * The application server instance itself.
55
     *
56
     * @var \AppserverIo\Psr\ApplicationServer\ApplicationServerInterface
57
     */
58
    protected static $instance;
59
60
    /**
61
     * Initialize and start the application server.
62
     *
63
     * @param \AppserverIo\Psr\Naming\NamingDirectoryInterface $namingDirectory The default naming directory
64
     * @param \AppserverIo\Storage\GenericStackable            $runlevels       The storage for the services
65
     */
66
    protected function __construct(NamingDirectoryInterface $namingDirectory, GenericStackable $runlevels)
67
    {
68
69
        // set the services and the naming directory
70
        $this->runlevels = $runlevels;
0 ignored issues
show
Bug Best Practice introduced by
The property runlevels does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
71
        $this->namingDirectory = $namingDirectory;
0 ignored issues
show
Bug Best Practice introduced by
The property namingDirectory does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
72
73
        // initialize the default runlevel
74
        $this->runlevel = ApplicationServerInterface::ADMINISTRATION;
0 ignored issues
show
Bug Best Practice introduced by
The property runlevel does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
75
76
        // set to TRUE, because we switch to runlevel 1 immediately
77
        $this->locked = false;
0 ignored issues
show
Bug Best Practice introduced by
The property locked does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
78
79
        // initialize command/params
80
        $this->command = null;
0 ignored issues
show
Bug Best Practice introduced by
The property command does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
81
        $this->params = null;
0 ignored issues
show
Bug Best Practice introduced by
The property params does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
82
    }
83
84
    /**
85
     * Creates a new singleton application server instance.
86
     *
87
     * @param \AppserverIo\Psr\Naming\NamingDirectoryInterface $namingDirectory The default naming directory
88
     * @param \AppserverIo\Storage\GenericStackable            $runlevels       The storage for the services
89
     *
90
     * @return \AppserverIo\Psr\ApplicationServer\ApplicationServerInterface The singleton application instance
91
     */
92
    public static function singleton(NamingDirectoryInterface $namingDirectory, GenericStackable $runlevels)
93
    {
94
95
        // query whether we already have an instance or not
96
        if (ApplicationServer::$instance == null) {
97
            // initialize and start the application server
98
            ApplicationServer::$instance = new ApplicationServer($namingDirectory, $runlevels);
99
            ApplicationServer::$instance->start();
100
        }
101
102
        // return the instance
103
        return ApplicationServer::$instance;
104
    }
105
106
    /**
107
     * Translates and returns a string representation of the passed runlevel.
108
     *
109
     * @param integer $runlevel The runlevel to return the string representation for
110
     *
111
     * @return string The string representation for the passed runlevel
112
     *
113
     * @throws \Exception Is thrown if the passed runlevel is not available
114
     */
115
    public function runlevelToString($runlevel)
116
    {
117
118
        // flip the array with the string => integer runlevel definitions
119
        $runlevels = array_flip(Runlevels::singleton()->getRunlevels());
120
        if (isset($runlevels[$runlevel])) {
121
            return $runlevels[$runlevel];
122
        }
123
124
        // throw an exception if the runlevel is unknown
125
        throw new \Exception(sprintf('Request invalid runlevel to string conversion for %s', $runlevel));
126
    }
127
128
    /**
129
     * Translates and returns the runlevel of the passed a string representation.
130
     *
131
     * @param string $runlevel The string representation of the runlevel to return
132
     *
133
     * @return integer The runlevel of the passed string representation
134
     *
135
     * @throws \Exception Is thrown if the passed string representation is not a valid runlevel
136
     */
137
    public function runlevelFromString($runlevel)
138
    {
139
140
        // query whether the passed string representation is a valid runlevel
141
        if (Runlevels::singleton()->isRunlevel($runlevel)) {
142
            return Runlevels::singleton()->getRunlevel($runlevel);
143
        }
144
145
        // throw an exception if the runlevel is unknown
146
        throw new \Exception(sprintf('Request invalid runlevel to string conversion for %s', $runlevel));
147
    }
148
149
    /**
150
     * Returns the naming directory instance.
151
     *
152
     * @return \AppserverIo\Psr\Naming\NamingDirectoryInterface $namingDirectory The default naming directory
153
     */
154
    public function getNamingDirectory()
155
    {
156
        return $this->namingDirectory;
157
    }
158
159
    /**
160
     * Sets the system configuration.
161
     *
162
     * @param \AppserverIo\Psr\ApplicationServer\Configuration\SystemConfigurationInterface $systemConfiguration The system configuration object
163
     *
164
     * @return null
165
     */
166
    public function setSystemConfiguration(SystemConfigurationInterface $systemConfiguration)
167
    {
168
        $this->systemConfiguration = $systemConfiguration;
0 ignored issues
show
Bug Best Practice introduced by
The property systemConfiguration does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
169
    }
170
171
    /**
172
     * Returns the system configuration.
173
     *
174
     * @return \AppserverIo\Psr\ApplicationServer\Configuration\SystemConfigurationInterface The system configuration
175
     */
176
    public function getSystemConfiguration()
177
    {
178
        return $this->systemConfiguration;
179
    }
180
181
    /**
182
     * Sets the initial context instance.
183
     *
184
     * @param \AppserverIo\Psr\ApplicationServer\ContextInterface $initialContext The initial context instance
185
     *
186
     * @return void
187
     */
188
    public function setInitialContext(ContextInterface $initialContext)
189
    {
190
        $this->initialContext = $initialContext;
0 ignored issues
show
Bug Best Practice introduced by
The property initialContext does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
191
    }
192
193
    /**
194
     * Return's the initial context instance.
195
     *
196
     * @return \AppserverIo\Psr\ApplicationServer\ContextInterface The initial context instance
197
     */
198
    public function getInitialContext()
199
    {
200
        return $this->initialContext;
201
    }
202
203
    /**
204
     * Set's the logger instances.
205
     *
206
     * @param array $loggers The logger instances to set
207
     *
208
     * @return void
209
     */
210
    public function setLoggers(array $loggers)
211
    {
212
        $this->loggers = $loggers;
0 ignored issues
show
Bug Best Practice introduced by
The property loggers does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
213
    }
214
215
    /**
216
     * Returns the logger instances.
217
     *
218
     * @return array The logger instances
219
     */
220
    public function getLoggers()
221
    {
222
        return $this->loggers;
223
    }
224
225
    /**
226
     * Returns the requested logger instance.
227
     *
228
     * @param string $name Name of the requested logger instance
229
     *
230
     * @return \Psr\Log\LoggerInterface|null The requested logger instance
231
     */
232
    public function getLogger($name)
233
    {
234
        if (isset($this->loggers[$name])) {
235
            return $this->loggers[$name];
236
        }
237
    }
238
239
    /**
240
     * Return's the system logger instance.
241
     *
242
     * @return \Psr\Log\LoggerInterface The system logger instance
243
     */
244
    public function getSystemLogger()
245
    {
246
247
        try {
248
            return $this->getNamingDirectory()->search(NamingDirectoryKeys::SYSTEM_LOGGER);
249
        } catch (NamingException $ne) {
250
            return new Logger('System');
251
        }
252
    }
253
254
    /**
255
     * Returns the name and the path of the system configuration file.
256
     *
257
     * @return string Name and path of the sytsem configuration file
258
     */
259
    public function getConfigurationFilename()
260
    {
261
        return $this->getNamingDirectory()->search('php:env/configurationFilename');
262
    }
263
264
    /**
265
     * Returns the name and the path of the bootstrap configuration file.
266
     *
267
     * @return string Name and path of the bootstrap configuraiton file
268
     */
269
    public function getBootstrapConfigurationFilename()
270
    {
271
        return $this->getNamingDirectory()->search('php:env/bootstrapConfigurationFilename');
272
    }
273
274
    /**
275
     * Returns a new instance of the passed API service.
276
     *
277
     * @param string $className The API service class name to return the instance for
278
     *
279
     * @return \AppserverIo\Psr\ApplicationServer\ServiceInterface The service instance
280
     * @see \AppserverIo\Appserver\Core\InitialContext::newService()
281
     */
282
    public function newService($className)
283
    {
284
        return $this->getInitialContext()->newService($className);
285
    }
286
287
    /**
288
     * The runlevel to switch to.
289
     *
290
     * @param \React\Socket\ConnectionInterface $conn     The connection resource
291
     * @param integer                           $runlevel The new runlevel to switch to
292
     *
293
     * @return void
294
     */
295
    public function init(ConnectionInterface $conn = null, $runlevel = ApplicationServerInterface::FULL)
296
    {
297
298
        // switch to the new runlevel
299
        $this->synchronized(function ($self, $newRunlevel) {
300
            // wait till the previous commands has been finished
301
            while ($self->locked === true) {
302
                sleep(1);
303
            }
304
305
            // set the command name
306
            $self->command = InitCommand::COMMAND;
307
308
            // lock process
309
            $self->locked = true;
310
            $self->params = $newRunlevel;
311
312
            // notify the AS to execute the command
313
            $self->notify();
314
315
        }, $this, $runlevel);
316
    }
317
318
    /**
319
     * Switch to the passed mode, which can either be 'dev', 'prod' or 'install'.
320
     *
321
     * @param \React\Socket\ConnectionInterface $conn The connection resource
322
     * @param string                            $mode The setup mode to switch to
323
     *
324
     * @return void
325
     */
326
    public function mode(ConnectionInterface $conn, $mode)
327
    {
328
329
        // switch to the new runlevel
330
        $this->synchronized(function ($self, $newMode) {
331
            // wait till the previous commands has been finished
332
            while ($self->locked === true) {
333
                sleep(1);
334
            }
335
336
            // set the command name
337
            $self->command = ModeCommand::COMMAND;
338
339
            // lock process
340
            $self->locked = true;
341
            $self->params = $newMode;
342
343
            // notify the AS to execute the command
344
            $self->notify();
345
346
        }, $this, $mode);
347
    }
348
349
    /**
350
     * Query whether the application server should keep running or not.
351
     *
352
     * @return boolean TRUE if the server should keep running, else FALSE
353
     */
354
    public function keepRunning()
355
    {
356
        return $this->synchronized(
357
            function ($self) {
358
                return $self->runlevel > ApplicationServerInterface::SHUTDOWN;
359
            },
360
            $this
361
        );
362
    }
363
364
    /**
365
     * Shutdown handler that checks for fatal/user errors.
366
     *
367
     * @return void
368
     */
369
    public function shutdown()
370
    {
371
        // check if there was a fatal error caused shutdown
372
        if ($lastError = error_get_last()) {
373
            // initialize type + message
374
            $type = 0;
375
            $message = '';
376
            // extract the last error values
377
            extract($lastError);
378
            // query whether we've a fatal/user error
379
            if ($type === E_ERROR || $type === E_USER_ERROR) {
380
                error_log($message);
381
            }
382
        }
383
    }
384
385
    /**
386
     * The thread's run() method that runs asynchronously.
387
     *
388
     * @return void
389
     * @link http://www.php.net/manual/en/thread.run.php
390
     */
391
    public function run()
392
    {
393
394
        // register a shutdown handler for controlled shutdown
395
        register_shutdown_function(array(&$this, 'shutdown'));
396
397
        // we need the autloader again
398
        require SERVER_AUTOLOADER;
399
400
        // create the service emitter
401
        $emitter = new Emitter();
402
403
        // load the bootstrap configuration
404
        /** @var \AppserverIo\Appserver\Core\Api\Node\BootstrapNodeInterface $bootstrapNode */
405
        $bootstrapNode = $this->doLoadBootstrap($this->getBootstrapConfigurationFilename());
406
407
        // iterate over the listeners and add them to the emitter
408
        /** @var \AppserverIo\Appserver\Core\Api\Node\ListenerNodeInterface $listener */
409
        foreach ($bootstrapNode->getListeners() as $listener) {
410
            // load the listener class name
411
            $listenerClassName = $listener->getType();
412
413
            // create a new instance of the listener class
414
            /** @var \League\Event\ListenerInterface $listenerInstance */
415
            $listenerInstance = new $listenerClassName();
416
417
            // query whether we've to inject the application server instance or not
418
            if ($listenerInstance instanceof ApplicationServerAwareListenerInterface) {
419
                $listenerInstance->injectApplicationServer($this);
420
            }
421
422
            // add the listeners
423
            $emitter->addListener($listener->getEvent(), $listenerInstance);
424
        }
425
426
        // synchronize the emitter
427
        $this->emitter = $emitter;
0 ignored issues
show
Bug Best Practice introduced by
The property emitter does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
428
429
        // override the default runlevel with the value found in the bootstrap configuration
430
        $this->runlevel = $this->runlevelFromString($bootstrapNode->getDefaultRunlevel());
0 ignored issues
show
Bug Best Practice introduced by
The property runlevel does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
Bug introduced by
$bootstrapNode->getDefaultRunlevel() of type array is incompatible with the type string expected by parameter $runlevel of AppserverIo\Appserver\Co...r::runlevelFromString(). ( Ignorable by Annotation )

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

430
        $this->runlevel = $this->runlevelFromString(/** @scrutinizer ignore-type */ $bootstrapNode->getDefaultRunlevel());
Loading history...
431
432
        // flag to keep the server running or to stop it
433
        $keepRunning = true;
434
435
        // initialize the actual runlevel with -1
436
        $actualRunlevel = -1;
437
438
        // start with the default runlevel
439
        $this->init(null, $this->runlevel);
440
441
        do {
442
            try {
443
                switch ($this->command) {
444
                    case InitCommand::COMMAND:
445
                        // copy command params -> the requested runlevel in that case
446
                        $this->runlevel = $this->params;
447
448
                        if ($this->runlevel == ApplicationServerInterface::REBOOT) {
449
                            // backup the runlevel
450
                            $backupRunlevel = $actualRunlevel;
451
452
                            // shutdown the application server
453
                            for ($i = $actualRunlevel; $i >= ApplicationServerInterface::SHUTDOWN; $i--) {
454
                                $this->emitter->emit(sprintf('leave.runlevel.%s', $this->runlevelToString($i)), $i);
455
                                // stop the services of the PREVIOUS runlevel
456
                                $this->doStopServices($i + 1);
457
                            }
458
459
                            // switch back to the runlevel we backed up before
460
                            for ($z = ApplicationServerInterface::SHUTDOWN; $z <= $backupRunlevel; $z++) {
461
                                $this->emitter->emit(sprintf('enter.runlevel.%s', $this->runlevelToString($z)), $z);
462
                            }
463
464
                            // set the runlevel to the one before we restart
465
                            $actualRunlevel = $backupRunlevel;
466
467
                            // reset the runlevel and the params
468
                            $this->runlevel = $this->params = $actualRunlevel;
0 ignored issues
show
Bug Best Practice introduced by
The property params does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
469
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
470
                        } elseif ($actualRunlevel == ApplicationServerInterface::SHUTDOWN) {
471
                            // we want to shutdown the application server
472
                            $keepRunning = false;
473
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
474
                        } elseif ($actualRunlevel < $this->runlevel) {
475
                            // switch to the requested runlevel
476
                            for ($i = $actualRunlevel + 1; $i <= $this->runlevel; $i++) {
477
                                $this->emitter->emit(sprintf('enter.runlevel.%s', $this->runlevelToString($i)), $i);
478
                            }
479
480
                            // set the new runlevel
481
                            $actualRunlevel = $this->runlevel;
482
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
483
                        } elseif ($actualRunlevel > $this->runlevel) {
484
                            // switch down to the requested runlevel
485
                            for ($i = $actualRunlevel; $i >= $this->runlevel; $i--) {
486
                                $this->emitter->emit(sprintf('leave.runlevel.%s', $this->runlevelToString($i)), $i);
487
                                // stop the services of the PREVIOUS runlevel
488
                                $this->doStopServices($i + 1);
489
                            }
490
491
                            // set the new runlevel
492
                            $actualRunlevel = $this->runlevel;
493
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
494
                        } else {
495
                            // signal that we've finished switching the runlevels and wait
496
                            $this->locked = false;
0 ignored issues
show
Bug Best Practice introduced by
The property locked does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
497
                            $this->command = null;
0 ignored issues
show
Bug Best Practice introduced by
The property command does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
498
499
                            // print a message and wait
500
                            $this->getSystemLogger()->info(sprintf('Switched to runlevel %s!!!', $actualRunlevel));
501
502
                            // wait for a new command
503
                            $this->synchronized(function ($self) {
504
                                $self->wait();
505
                            }, $this);
506
                        }
507
508
                        break;
509
510
                    case ModeCommand::COMMAND:
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
511
512
                        // switch the application server mode
513
                        $this->doSwitchSetupMode($this->params, $this->getConfigurationFilename());
514
515
                        // singal that we've finished setting umask and wait
516
                        $this->locked = false;
517
                        $this->command = null;
518
519
                        // wait for a new command
520
                        $this->synchronized(function ($self) {
521
                            $self->wait();
522
                        }, $this);
523
524
                        break;
525
526
                    default:
0 ignored issues
show
Coding Style introduced by
The default body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a default statement must start on the line immediately following the statement.

switch ($expr) {
    default:
        doSomething(); //right
        break;
}


switch ($expr) {
    default:

        doSomething(); //wrong
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
527
528
                        // print a message and wait
529
                         $this->getSystemLogger()->info('Can\'t find any command!!!');
530
531
                        // singal that we've finished setting umask and wait
532
                        $this->locked = false;
533
534
                        // wait for a new command
535
                        $this->synchronized(function ($self) {
536
                            $self->wait();
537
                        }, $this);
538
539
                        break;
540
                }
541
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
542
            } catch (\Exception $e) {
543
                $this->getSystemLogger()->error($e->getMessage());
544
            }
545
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
546
        } while ($keepRunning);
547
    }
548
549
    /**
550
     * Returns the service for the passed runlevel and name.
551
     *
552
     * @param integer $runlevel The runlevel of the requested service
553
     * @param string  $name     The name of the requested service
554
     *
555
     * @return mixed The service instance
556
     */
557
    public function getService($runlevel, $name)
558
    {
559
        return $this->runlevels[$runlevel][$name];
560
    }
561
562
    /**
563
     * Unbind the service with the passed name and runlevel.
564
     *
565
     * @param integer $runlevel The runlevel of the service
566
     * @param string  $name     The name of the service
567
     *
568
     * @return void
569
     */
570
    public function unbindService($runlevel, $name)
571
    {
572
573
        // stop the service instance
574
        $this->runlevels[$runlevel][$name]->stop();
575
576
        // unbind the service from the naming directory
577
        $this->getNamingDirectory()->unbind(sprintf('php:services/%s/%s', $this->runlevelToString($runlevel), $name));
578
579
        // unset the service instance
580
        unset($this->runlevels[$runlevel][$name]);
581
582
        // print a message that the service has been stopped
583
        $this->getSystemLogger()->info(sprintf('Successfully stopped service %s', $name));
584
    }
585
586
    /**
587
     * Binds the passed service to the runlevel.
588
     *
589
     * @param integer $runlevel The runlevel to bound the service to
590
     * @param object  $service  The service to bound
591
     *
592
     * @return void
593
     */
594
    public function bindService($runlevel, $service)
595
    {
596
597
        // bind the service to the runlevel
598
        $this->runlevels[$runlevel][$service->getName()] = $service;
0 ignored issues
show
Bug Best Practice introduced by
The property runlevels does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
599
600
        // bind the service callback to the naming directory
601
        $this->getNamingDirectory()->bindCallback(
602
            sprintf('php:services/%s/%s', $this->runlevelToString($runlevel), $service->getName()),
603
            array(&$this, 'getService'),
604
            array($runlevel, $service->getName())
605
        );
606
    }
607
608
    /**
609
     * Stops all services of the passed runlevel.
610
     *
611
     * @param integer $runlevel The runlevel to stop all services for
612
     *
613
     * @return void
614
     */
615
    public function stopServices($runlevel)
616
    {
617
        $this->doStopServices($runlevel);
618
    }
619
620
    /**
621
     * Loads the bootstrap configuration from the XML file.
622
     *
623
     * @param string $bootstrapConfigurationFilename The boostrap configuration file
624
     *
625
     * @return \AppserverIo\Appserver\Core\Api\Node\BootstrapNode The boostrap configuration
626
     */
627
    protected function doLoadBootstrap($bootstrapConfigurationFilename)
628
    {
629
630
        // initialize the bootstrap configuration
631
        $bootstrapNode = new BootstrapNode();
632
        $bootstrapNode->initFromFile($bootstrapConfigurationFilename);
0 ignored issues
show
Bug introduced by
$bootstrapConfigurationFilename of type string is incompatible with the type AppserverIo\Lang\String expected by parameter $filename of AppserverIo\Description\...actNode::initFromFile(). ( Ignorable by Annotation )

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

632
        $bootstrapNode->initFromFile(/** @scrutinizer ignore-type */ $bootstrapConfigurationFilename);
Loading history...
633
634
        // return the bootstrap configuration
635
        return $bootstrapNode;
636
    }
637
638
    /**
639
     * Stops all services of the passed runlevel.
640
     *
641
     * @param integer $runlevel The runlevel to stop all services for
642
     *
643
     * @return void
644
     */
645
    protected function doStopServices($runlevel)
646
    {
647
        // iterate over all services and stop them
648
        foreach (array_flip($this->runlevels[$runlevel]) as $name) {
649
            $this->unbindService($runlevel, $name);
650
        }
651
    }
652
653
    /**
654
     * Switches the running setup mode to the passed value.
655
     *
656
     * @param string $newMode               The mode to switch to
657
     * @param string $configurationFilename The path of the configuration filename
658
     *
659
     * @return void
660
     * @throws \Exception Is thrown for an invalid setup mode passed
661
     */
662
    protected function doSwitchSetupMode($newMode, $configurationFilename)
663
    {
664
        // load the current user from the naming directory
665
        $currentUser = $this->getNamingDirectory()->search('php:env/currentUser');
666
667
        // load the service instance and switch to the new setup mode
668
        /** @var \AppserverIo\Appserver\Core\Api\ContainerService $service */
669
        $service = $this->newService('AppserverIo\Appserver\Core\Api\ContainerService');
670
        $service->switchSetupMode($newMode, $configurationFilename, $currentUser);
671
    }
672
}
673