|
1
|
|
|
<?php |
|
2
|
|
|
namespace PjbServer\Tools; |
|
3
|
|
|
|
|
4
|
|
|
class StandaloneServer |
|
5
|
|
|
{ |
|
6
|
|
|
/** |
|
7
|
|
|
* @var int |
|
8
|
|
|
*/ |
|
9
|
|
|
protected $port; |
|
10
|
|
|
|
|
11
|
|
|
/** |
|
12
|
|
|
* |
|
13
|
|
|
* @var array |
|
14
|
|
|
*/ |
|
15
|
|
|
protected $config; |
|
16
|
|
|
|
|
17
|
|
|
|
|
18
|
|
|
/** |
|
19
|
|
|
* Tells whether the standalone server is started |
|
20
|
|
|
* @var boolean |
|
21
|
|
|
*/ |
|
22
|
|
|
protected $started = false; |
|
23
|
|
|
|
|
24
|
|
|
/** |
|
25
|
|
|
* @var array |
|
26
|
|
|
*/ |
|
27
|
|
|
protected $required_arguments = array( |
|
28
|
|
|
'port' => 'FILTER_VALIDATE_INT', |
|
29
|
|
|
'server_jar' => 'existing_file', |
|
30
|
|
|
'error_file' => 'file_with_existing_directory', |
|
31
|
|
|
'pid_file' => 'file_with_existing_directory', |
|
32
|
|
|
); |
|
33
|
|
|
|
|
34
|
|
|
/** |
|
35
|
|
|
* Default configuration options |
|
36
|
|
|
* @var array |
|
37
|
|
|
*/ |
|
38
|
|
|
protected $default_config = array( |
|
39
|
|
|
'server_jar' => '{base_dir}/resources/pjb621_standalone/JavaBridge.jar', |
|
40
|
|
|
'java_bin' => 'java', |
|
41
|
|
|
'error_file' => '{base_dir}/resources/pjb621_standalone/logs/pjbserver-port{tcp_port}-error.log', |
|
42
|
|
|
'pid_file' => '{base_dir}/resources/pjb621_standalone/var/run/pjbserver-port{tcp_port}.pid' |
|
43
|
|
|
); |
|
44
|
|
|
|
|
45
|
|
|
/** |
|
46
|
|
|
* Constructor |
|
47
|
|
|
* |
|
48
|
|
|
* <code> |
|
49
|
|
|
* |
|
50
|
|
|
* $config = array( |
|
51
|
|
|
* 'port' => 8089, |
|
52
|
|
|
* |
|
53
|
|
|
* // optionally |
|
54
|
|
|
* 'server_jar' => 'path/to/JavaBridge.jar' |
|
55
|
|
|
* 'java_bin' => 'path/to/java' |
|
56
|
|
|
* ); |
|
57
|
|
|
* $server = new StandaloneServer($config); |
|
58
|
|
|
* |
|
59
|
|
|
* </code> |
|
60
|
|
|
* |
|
61
|
|
|
* @throws Exception\InvalidArgumentException |
|
62
|
|
|
* @param array $config |
|
63
|
|
|
*/ |
|
64
|
8 |
|
public function __construct(array $config) |
|
65
|
|
|
{ |
|
66
|
8 |
|
if (!isset($config['port'])) { |
|
67
|
3 |
|
throw new Exception\InvalidArgumentException("Error missing required 'port' in config"); |
|
68
|
5 |
|
} elseif (!filter_var($config['port'], FILTER_VALIDATE_INT)) { |
|
69
|
1 |
|
throw new Exception\InvalidArgumentException("Option 'port' must be numeric"); |
|
70
|
|
|
} |
|
71
|
4 |
|
$config = array_merge($this->getDefaultConfig($config['port']), $config); |
|
72
|
4 |
|
$this->checkConfigRequiredArgs($config); |
|
73
|
3 |
|
$this->setServerPort($config['port']); |
|
74
|
3 |
|
$this->config = $config; |
|
75
|
3 |
|
} |
|
76
|
|
|
|
|
77
|
|
|
|
|
78
|
|
|
/** |
|
79
|
|
|
* Start the standalone server |
|
80
|
|
|
* @return void |
|
81
|
|
|
*/ |
|
82
|
2 |
|
public function start() |
|
83
|
|
|
{ |
|
84
|
2 |
|
$port = $this->getServerPort(); |
|
85
|
|
|
|
|
86
|
2 |
|
$java_bin = $this->config['java_bin']; |
|
87
|
|
|
|
|
88
|
|
|
$classpath = array( |
|
89
|
2 |
|
$this->config['server_jar'], |
|
90
|
2 |
|
); |
|
91
|
|
|
|
|
92
|
2 |
|
$classpath = join(':', $classpath); |
|
93
|
2 |
|
$command = "$java_bin -cp $classpath php.java.bridge.Standalone SERVLET:$port"; |
|
94
|
|
|
|
|
95
|
2 |
|
$error_file = $this->config['error_file']; |
|
96
|
2 |
|
$pid_file = $this->config['pid_file']; |
|
97
|
2 |
|
$cmd = sprintf("%s > %s 2>&1 & echo $! > %s", $command, $error_file, $pid_file); |
|
98
|
|
|
|
|
99
|
|
|
//echo $cmd . "\n"; |
|
|
|
|
|
|
100
|
2 |
|
exec($cmd); |
|
101
|
|
|
|
|
102
|
2 |
|
$this->started = true; |
|
103
|
|
|
|
|
104
|
|
|
|
|
105
|
2 |
|
} |
|
106
|
|
|
|
|
107
|
2 |
|
public function stop() |
|
108
|
|
|
{ |
|
109
|
2 |
|
unlink($this->config['pid_file']); |
|
110
|
|
|
|
|
111
|
2 |
|
$this->started = false; |
|
112
|
2 |
|
} |
|
113
|
|
|
|
|
114
|
|
|
/** |
|
115
|
|
|
* Tells whether the standalone server is started |
|
116
|
|
|
* @return boolean |
|
117
|
|
|
*/ |
|
118
|
1 |
|
public function isStarted() |
|
119
|
|
|
{ |
|
120
|
1 |
|
return $this->started; |
|
121
|
|
|
} |
|
122
|
|
|
|
|
123
|
|
|
/** |
|
124
|
|
|
* Get runnin standalone server pid number |
|
125
|
|
|
* |
|
126
|
|
|
* @throws Exception\RuntimeException |
|
127
|
|
|
* @return int |
|
128
|
|
|
*/ |
|
129
|
1 |
|
public function getPid() |
|
130
|
|
|
{ |
|
131
|
1 |
|
$pid_file = $this->config['pid_file']; |
|
132
|
1 |
|
if (!file_exists($pid_file)) { |
|
133
|
|
|
$msg = "Pid file cannot be found '$pid_file'"; |
|
134
|
|
|
throw new Exception\RuntimeException($msg); |
|
135
|
|
|
} |
|
136
|
1 |
|
return trim(file_get_contents($pid_file)); |
|
137
|
|
|
} |
|
138
|
|
|
|
|
139
|
|
|
|
|
140
|
|
|
/** |
|
141
|
|
|
* Restart the standalone server |
|
142
|
|
|
*/ |
|
143
|
|
|
public function restart() |
|
144
|
|
|
{ |
|
145
|
|
|
$this->stop(); |
|
146
|
|
|
$this->start(); |
|
147
|
|
|
} |
|
148
|
|
|
|
|
149
|
|
|
/** |
|
150
|
|
|
* Return port on which standalone server listens |
|
151
|
|
|
* @return int |
|
152
|
|
|
*/ |
|
153
|
3 |
|
public function getServerPort() |
|
154
|
|
|
{ |
|
155
|
3 |
|
return $this->port; |
|
156
|
|
|
} |
|
157
|
|
|
|
|
158
|
|
|
/** |
|
159
|
|
|
* Set port on which standalone server listens. |
|
160
|
|
|
* |
|
161
|
|
|
* @param int $port |
|
162
|
|
|
* @return void |
|
163
|
|
|
*/ |
|
164
|
3 |
|
protected function setServerPort($port) |
|
165
|
|
|
{ |
|
166
|
3 |
|
$this->port = $port; |
|
167
|
3 |
|
} |
|
168
|
|
|
|
|
169
|
|
|
/** |
|
170
|
|
|
* Return default configuration options |
|
171
|
|
|
* @param int $tcp_port |
|
|
|
|
|
|
172
|
|
|
* @return array |
|
173
|
|
|
*/ |
|
174
|
4 |
|
protected function getDefaultConfig($port) |
|
175
|
|
|
{ |
|
176
|
4 |
|
$base_dir = realpath(__DIR__ . '/../../../'); |
|
177
|
4 |
|
$config = array(); |
|
178
|
4 |
|
foreach ($this->default_config as $key => $value) { |
|
179
|
4 |
|
$tmp = str_replace('{base_dir}', $base_dir, $value); |
|
180
|
4 |
|
$tmp = str_replace('{tcp_port}', $port, $tmp); |
|
181
|
4 |
|
$config[$key] = $tmp; |
|
182
|
4 |
|
} |
|
183
|
4 |
|
return $config; |
|
184
|
|
|
} |
|
185
|
|
|
|
|
186
|
|
|
/** |
|
187
|
|
|
* Check configuration parameters |
|
188
|
|
|
* @throws Exception\InvalidArgumentException |
|
189
|
|
|
* @param array $config |
|
190
|
|
|
*/ |
|
191
|
4 |
|
protected function checkConfigRequiredArgs(array $config) |
|
192
|
|
|
{ |
|
193
|
4 |
|
foreach ($this->required_arguments as $name => $type) { |
|
194
|
4 |
|
if (!isset($config[$name])) { |
|
195
|
|
|
$msg = "Missing option '$name' in Standalone server configuration"; |
|
196
|
|
|
throw new Exception\InvalidArgumentException($msg); |
|
197
|
|
|
} |
|
198
|
4 |
|
if (is_long($type) && !filter_var($config[$name], $type)) { |
|
199
|
|
|
$msg = "Unsupported type in option '$name' in Standalone server configuration (required $type)"; |
|
200
|
|
|
throw new Exception\InvalidArgumentException($msg); |
|
201
|
4 |
|
} elseif (is_string($type)) { |
|
202
|
|
|
switch ($type) { |
|
203
|
4 |
|
case 'existing_file': |
|
204
|
4 |
|
$file = $config[$name]; |
|
205
|
4 |
|
if (!file_exists($file)) { |
|
206
|
1 |
|
$msg = "The '$name' file '$file 'does not exists."; |
|
207
|
1 |
|
throw new Exception\InvalidArgumentException($msg); |
|
208
|
|
|
} |
|
209
|
3 |
|
break; |
|
210
|
4 |
|
case 'file_with_existing_directory': |
|
211
|
3 |
|
$file = $config[$name]; |
|
212
|
3 |
|
$info = pathinfo($file); |
|
213
|
3 |
|
$dirname = $info['dirname']; |
|
214
|
3 |
|
if (!is_dir($dirname) || $dirname == ".") { |
|
215
|
|
|
$msg = "Option '$name' refer to an invalid or non-existent directory ($file)"; |
|
216
|
|
|
throw new Exception\InvalidArgumentException($msg); |
|
217
|
|
|
} |
|
218
|
3 |
|
if (is_dir($file)) { |
|
219
|
|
|
$msg = "Option '$name' does not refer to a file but an existing directory ($file)"; |
|
220
|
|
|
throw new Exception\InvalidArgumentException($msg); |
|
221
|
|
|
} |
|
222
|
3 |
|
if (file_exists($file) && !is_writable($file)) { |
|
223
|
|
|
$msg = "File specified in '$name' is not writable ($file)"; |
|
224
|
|
|
throw new Exception\InvalidArgumentException($msg); |
|
225
|
|
|
} |
|
226
|
3 |
|
break; |
|
227
|
|
|
} |
|
228
|
4 |
|
} |
|
229
|
4 |
|
} |
|
230
|
3 |
|
} |
|
231
|
|
|
} |
|
232
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.