1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* \AppserverIo\Server\Standalone |
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 Johann Zelger <[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/server |
18
|
|
|
* @link http://www.appserver.io |
19
|
|
|
*/ |
20
|
|
|
|
21
|
|
|
namespace AppserverIo\Server; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* Class Standalone |
25
|
|
|
* |
26
|
|
|
* To use the a server implementation standalone |
27
|
|
|
* |
28
|
|
|
* @author Johann Zelger <[email protected]> |
29
|
|
|
* @copyright 2015 TechDivision GmbH <[email protected]> |
30
|
|
|
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) |
31
|
|
|
* @link https://github.com/appserver-io/server |
32
|
|
|
* @link http://www.appserver.io |
33
|
|
|
*/ |
34
|
|
|
class Standalone |
35
|
|
|
{ |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Constructs the standalone bootstrapping |
39
|
|
|
* |
40
|
|
|
* @param string $baseDir The base directory of the server to start in standalone mode |
41
|
|
|
* @param string $configFile The servers config file |
42
|
|
|
* @param string $autoloaderFile The autoloader file to use |
43
|
|
|
*/ |
44
|
|
|
public function __construct($baseDir, $configFile = null, $autoloaderFile = null) |
45
|
|
|
{ |
46
|
|
|
// check if baseDir has trailing slash and add it if not |
47
|
|
|
if (substr($baseDir, -1) !== '/') { |
48
|
|
|
$baseDir .= '/'; |
49
|
|
|
} |
50
|
|
|
// defines the server basedir |
51
|
|
|
define('SERVER_BASEDIR', $baseDir); |
52
|
|
|
// defines the autoloader to use within the server standalone process |
53
|
|
|
define('SERVER_AUTOLOADER', $autoloaderFile); |
54
|
|
|
// check if user defined configuration is passed via argv |
55
|
|
|
if (!is_null($configFile)) { |
56
|
|
|
define('SERVER_CONFIGFILE', $configFile); |
57
|
|
|
} else { |
58
|
|
|
define('SERVER_CONFIGFILE', SERVER_BASEDIR . 'etc/server.xml'); |
59
|
|
|
} |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* Checks compatibility of environment |
64
|
|
|
* |
65
|
|
|
* @return void |
66
|
|
|
*/ |
67
|
|
|
public function checkEnvironment() |
68
|
|
|
{ |
69
|
|
|
if (!PHP_ZTS) { |
70
|
|
|
die('This php build is not thread safe. Please recompile with option --enable-maintainer-zts' . PHP_EOL); |
|
|
|
|
71
|
|
|
} |
72
|
|
|
if (version_compare(PHP_VERSION, '7.0.0', '<') && !extension_loaded('appserver')) { |
73
|
|
|
die('Required php extension "appserver" not found. See https://github.com/techdivision/php-ext-appserver' . PHP_EOL); |
|
|
|
|
74
|
|
|
} |
75
|
|
|
if (!extension_loaded('pthreads')) { |
76
|
|
|
die('Required php extension "pthreads" not found. See https://github.com/krakjoe/pthreads' . PHP_EOL); |
|
|
|
|
77
|
|
|
} |
78
|
|
|
if (!is_file(SERVER_CONFIGFILE)) { |
79
|
|
|
die('Configuration file not exists "' . SERVER_CONFIGFILE . '"'. PHP_EOL); |
|
|
|
|
80
|
|
|
} |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* Starts the server in standalone mode |
85
|
|
|
* |
86
|
|
|
* @throws \Exception |
87
|
|
|
* @return void |
88
|
|
|
*/ |
89
|
|
|
public function start() |
90
|
|
|
{ |
91
|
|
|
// check environment first |
92
|
|
|
$this->checkEnvironment(); |
93
|
|
|
|
94
|
|
|
// register autoloader if exists |
95
|
|
|
if (!is_null(SERVER_AUTOLOADER)) { |
96
|
|
|
require SERVER_AUTOLOADER; |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
// check which config format should be used based on file extension |
100
|
|
|
if ($configType = str_replace('.', '', strrchr(SERVER_CONFIGFILE, '.'))) { |
101
|
|
|
$mainConfigurationType = '\AppserverIo\Server\Configuration\Main' . ucfirst($configType) . 'Configuration'; |
102
|
|
|
// try to instantiate configuration type based on file |
103
|
|
|
if (class_exists($mainConfigurationType)) { |
104
|
|
|
$mainConfiguration = new $mainConfigurationType(SERVER_CONFIGFILE); |
105
|
|
|
} else { |
106
|
|
|
die("Configuration file '$configType' is not valid or not found.". PHP_EOL); |
|
|
|
|
107
|
|
|
} |
108
|
|
|
} else { |
109
|
|
|
die("No valid configuration file given." . PHP_EOL); |
|
|
|
|
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
// init loggers |
113
|
|
|
$loggers = array(); |
114
|
|
|
foreach ($mainConfiguration->getLoggerConfigs() as $loggerConfig) { |
115
|
|
|
// init processors |
116
|
|
|
$processors = array(); |
117
|
|
|
foreach ($loggerConfig->getProcessors() as $processorType) { |
118
|
|
|
// create processor |
119
|
|
|
$processors[] = new $processorType(); |
120
|
|
|
} |
121
|
|
|
// init handlers |
122
|
|
|
$handlers = array(); |
123
|
|
|
foreach ($loggerConfig->getHandlers() as $handlerType => $handlerData) { |
124
|
|
|
// create handler |
125
|
|
|
$handlerTypeClass = new \ReflectionClass($handlerType); |
126
|
|
|
$handler = $handlerTypeClass->newInstanceArgs($handlerData["params"]); |
127
|
|
|
if (isset($handlerData['formatter'])) { |
128
|
|
|
$formatterData = $handlerData['formatter']; |
129
|
|
|
$formatterType = $formatterData['type']; |
130
|
|
|
// create formatter |
131
|
|
|
$formatterClass = new \ReflectionClass($formatterType); |
132
|
|
|
$formatter = $formatterClass->newInstanceArgs($formatterData['params']); |
133
|
|
|
// set formatter to logger |
134
|
|
|
$handler->setFormatter($formatter); |
135
|
|
|
} |
136
|
|
|
$handlers[] = $handler; |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
// get logger type |
140
|
|
|
$loggerType = $loggerConfig->getType(); |
141
|
|
|
// init logger instance |
142
|
|
|
$logger = new $loggerType($loggerConfig->getName(), $handlers, $processors); |
143
|
|
|
|
144
|
|
|
$logger->debug(sprintf('logger initialised: %s (%s)', $loggerConfig->getName(), $loggerType)); |
145
|
|
|
|
146
|
|
|
// set logger by name |
147
|
|
|
$loggers[$loggerConfig->getName()] = $logger; |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
// init upstreams |
151
|
|
|
$upstreams = array(); |
152
|
|
|
foreach ($mainConfiguration->getUpstreamConfigs() as $upstreamConfig) { |
153
|
|
|
// get upstream type |
154
|
|
|
$upstreamType = $upstreamConfig->getType(); |
155
|
|
|
// init upstream instance |
156
|
|
|
$upstream = new $upstreamType(); |
157
|
|
|
// init upstream servers |
158
|
|
|
$servers = array(); |
159
|
|
|
foreach ($upstreamConfig->getServers() as $serverName => $serverData) { |
160
|
|
|
$serverType = $serverData['type']; |
161
|
|
|
$serverParams = $serverData['params']; |
162
|
|
|
$servers[$serverName] = new $serverType($serverParams); |
163
|
|
|
} |
164
|
|
|
// inject server instances to upstream |
165
|
|
|
$upstream->injectServers($servers); |
166
|
|
|
// set upstream by name |
167
|
|
|
$upstreams[$upstreamConfig->getName()] = $upstream; |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
// init servers |
171
|
|
|
$servers = array(); |
172
|
|
|
foreach ($mainConfiguration->getServerConfigs() as $serverConfig) { |
173
|
|
|
// get type definitions |
174
|
|
|
$serverType = $serverConfig->getType(); |
175
|
|
|
$serverContextType = $serverConfig->getServerContextType(); |
176
|
|
|
|
177
|
|
|
// init server context |
178
|
|
|
$serverContext = new $serverContextType(); |
179
|
|
|
$serverContext->init($serverConfig); |
180
|
|
|
|
181
|
|
|
// check if logger name exists |
182
|
|
|
if (isset($loggers[$serverConfig->getLoggerName()])) { |
183
|
|
|
$serverContext->injectLoggers($loggers); |
184
|
|
|
} else { |
185
|
|
|
throw new \Exception(sprintf('Logger %s not found.', $serverConfig->getLoggerName())); |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
// inject upstreams to server context |
189
|
|
|
$serverContext->injectUpstreams($upstreams); |
190
|
|
|
|
191
|
|
|
// Create the server (which should start it automatically) |
192
|
|
|
$server = new $serverType($serverContext); |
193
|
|
|
// Collect the servers we started |
194
|
|
|
$servers[] = $server; |
195
|
|
|
|
196
|
|
|
// Synchronize the server so we can wait until preparation of the server finished. |
197
|
|
|
// This is used e.g. to wait for port opening or other important dependencies to proper server functionality |
198
|
|
|
|
199
|
|
|
/* |
200
|
|
|
$server->synchronized( |
201
|
|
|
function ($self) { |
202
|
|
|
$self->wait(); |
203
|
|
|
}, |
204
|
|
|
$server |
205
|
|
|
); |
206
|
|
|
*/ |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
// @TODO here we are able to switch user to someone with lower rights (e.g. www-data or nobody) |
|
|
|
|
210
|
|
|
|
211
|
|
|
// wait for servers |
212
|
|
|
foreach ($servers as $server) { |
213
|
|
|
$server->join(); |
214
|
|
|
} |
215
|
|
|
} |
216
|
|
|
} |
217
|
|
|
|
An exit expression should only be used in rare cases. For example, if you write a short command line script.
In most cases however, using an
exit
expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.