Completed
Push — master ( b645d7...565ce2 )
by Sébastien
04:19
created

Config::getLogFile()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
namespace PjbServer\Tools\StandaloneServer;
4
5
use PjbServer\Tools\Exception;
6
7
/*
8
  java -Djava.awt.headless="true"
9
  -Dphp.java.bridge.threads=50
10
  -Dphp.java.bridge.base=/usr/lib/php/modules
11
  -Dphp.java.bridge.php_exec=/usr/local/bin/php-cgi
12
  -Dphp.java.bridge.default_log_file=
13
  -Dphp.java.bridge.default_log_level=5
14
  -Dphp.java.bridge.daemon="false"
15
  -jar JavaBridge.jar
16
 * sudo netstat -anltp|grep :8089
17
 */
18
19
class Config
20
{
21
    /**
22
     * Default configuration options.
23
     *
24
     * @var array
25
     */
26
    protected $default_config = [
27
        'java_bin' => 'java',
28
        'server_jar' => '{base_dir}/resources/pjb621_standalone/JavaBridge.jar',
29
        'log_file' => '{base_dir}/var/pjbserver-port{tcp_port}.log',
30
        'pid_file' => '{base_dir}/var/pjbserver-port{tcp_port}.pid',
31
        'classpaths' => [],
32
        'threads' => 50
33
    ];
34
35
    /**
36
     * Internal configuration array.
37
     *
38
     * @var array
39
     */
40
    protected $config;
41
42
    /**
43
     * Constructor.
44
     *
45
     * <code>
46
     *
47
     * $params = [
48
     *      // Port (required)
49
     *      'port' => 8089,
50
     *
51
     *      // Classpath autoloads (optional)
52
     *      'classpaths' => [
53
     *          '/my/path/to_specific/jar_file.jar',
54
     *          '/my/path/to_all_jars/*.jar'
55
     *      ],
56
     *
57
     *      'threads' => 50,
58
     *
59
     *      // Defaults (optional)
60
     *      'java_bin'   => 'java',
61
     *      'server_jar' => '{base_dir}/resources/pjb621_standalone/JavaBridge.jar',
62
     *      'log_file'   => '{base_dir}/var/pjbserver-port{tcp_port}.log',
63
     *      'pid_file'   => '{base_dir}/var/pjbserver-port{tcp_port}.pid'
64
     *
65
     * ];
66
     * $config = new StandaloneServer\Config($params);
67
     * </code>
68
     *
69
     * @throws Exception\InvalidArgumentException
70
     *
71
     * @param array $config
72
     */
73 33
    public function __construct(array $config)
74
    {
75 33
        if (!isset($config['port'])) {
76 3
            throw new Exception\InvalidArgumentException("Error missing required 'port' in config");
77 30
        } elseif (!filter_var($config['port'], FILTER_VALIDATE_INT) || $config['port'] < 1) {
78 1
            throw new Exception\InvalidArgumentException("Option 'port' must be numeric greater than 0");
79
        }
80 29
        $port = $config['port'];
81
        // Substitute magic vars is deprecated and will be removed in v1.0.0
82 29
        $config = array_merge(
83 29
                        $this->getDefaultConfig($port),
84 29
                        $this->substitutePlaceholders($config, $port));
85 29
        $this->checkConfig($config);
86 28
        $this->config = $config;
87 28
    }
88
89
    /**
90
     * Return port on which standalone server listens.
91
     *
92
     * @return int
93
     */
94 19
    public function getPort()
95
    {
96 19
        return $this->config['port'];
97
    }
98
99
    /**
100
     * Return jar file of the server.
101
     *
102
     * @return string
103
     */
104 19
    public function getServerJar()
105
    {
106 19
        return $this->config['server_jar'];
107
    }
108
109
    /**
110
     * Return java binary.
111
     *
112
     * @return string
113
     */
114 19
    public function getJavaBin()
115
    {
116 19
        return $this->config['java_bin'];
117
    }
118
119
    /**
120
     * Return log file.
121
     *
122
     * @return string
123
     */
124 19
    public function getLogFile()
125
    {
126 19
        return $this->config['log_file'];
127
    }
128
129
    /**
130
     * Return an array containing the java classpath(s) for the server.
131
     *
132
     * @return array
133
     */
134 19
    public function getClasspaths()
135
    {
136 19
        return $this->config['classpaths'];
137
    }
138
139
    /**
140
     * Return pid file where to store process id.
141
     *
142
     * @return string
143
     */
144 23
    public function getPidFile()
145
    {
146 23
        return $this->config['pid_file'];
147
    }
148
149
    /**
150
     * Return standalone server threads.
151
     *
152
     * @return int|string
153
     */
154 16
    public function getThreads()
155
    {
156 16
        return $this->config['threads'];
157
    }
158
159
    /**
160
     * Return standalone configuration.
161
     *
162
     * @return array
163
     */
164 5
    public function toArray()
165
    {
166 5
        return $this->config;
167
    }
168
169
    /**
170
     * Return standalone configuration.
171
     *
172
     * @deprecated use toArray() instead
173
     *
174
     * @return array
175
     */
176
    public function getConfig()
177
    {
178
        return $this->toArray();
179
    }
180
181
    /**
182
     * Return default configuration options.
183
     *
184
     * @param int $port
185
     *
186
     * @return array
187
     */
188 29
    protected function getDefaultConfig($port)
189
    {
190 29
        return $this->substitutePlaceholders($this->default_config, $port);
191
    }
192
193
    /**
194
     * Substitute the placeholder {tcp_port} and {base_dir}
195
     * from a config array.
196
     *
197
     * @param array $configArray associative array
198
     *
199
     * @return array
200
     */
201 29
    protected function substitutePlaceholders(array $configArray, $port)
202
    {
203 29
        $substituted = [];
204 29
        $base_dir = $this->getBaseDir();
205
206 29
        foreach ($configArray as $key => $value) {
207 29
            $tmp = str_replace('{base_dir}', $base_dir, $value);
208 29
            $tmp = str_replace('{tcp_port}', $port, $tmp);
209 29
            $substituted[$key] = $tmp;
210 29
        }
211
212 29
        return $substituted;
213
    }
214
215
    /**
216
     * Return pjbserver-tools installation base directory.
217
     *
218
     * @throws Exception\RuntimeException
219
     *
220
     * @return string
221
     */
222 29
    public function getBaseDir()
223
    {
224
        // Four levels back.
225 29
        $ds = DIRECTORY_SEPARATOR;
226 29
        $dir = __DIR__ . "$ds..$ds..$ds..$ds..$ds";
227 29
        $base_dir = realpath($dir);
228 29
        if (!$base_dir) {
229
            $message = 'Cannot resolve project base directory.';
230
            throw new Exception\RuntimeException($message);
231
        }
232
233 29
        return $base_dir;
234
    }
235
236
    /**
237
     * Check configuration parameters.
238
     *
239
     * @throws Exception\InvalidArgumentException
240
     *
241
     * @param array $config
242
     */
243 29
    protected function checkConfig(array $config)
244
    {
245
        // Step 1: all required options
246 29
        $required = ['port', 'server_jar', 'log_file', 'pid_file', 'threads'];
247 29
        foreach ($required as $option) {
248 29
            if (!isset($config[$option]) || $config[$option] == '') {
249
                throw new Exception\InvalidArgumentException("Missing resuired configuration option: '$option''");
250
            }
251 29
        }
252
253
        // Step 2: server_jar file must exists
254 29
        if (!is_file($config['server_jar']) || !is_readable($config['server_jar'])) {
255 1
            throw new Exception\InvalidArgumentException("Server jar file not exists or unreadable. server-jar: '" . $config['server_jar'] . "'");
256
        }
257
258
        // Step 3: log and pid file should be creatable
259 28
        $temp_required_files = ['log_file', 'pid_file'];
260 28
        foreach ($temp_required_files as $option) {
261 28
            $file = $config[$option];
262 28
            $info = pathinfo($file);
263 28
            $dirname = $info['dirname'];
264 28
            if (!is_dir($dirname) || $dirname == '.') {
265
                $msg = "Option '$option' refer to an invalid or non-existent directory ($file)";
266
                throw new Exception\InvalidArgumentException($msg);
267
            }
268 28
            if (is_dir($file)) {
269
                $msg = "Option '$option' does not refer to a file but an existing directory ($file)";
270
                throw new Exception\InvalidArgumentException($msg);
271
            }
272 28
            if (file_exists($file) && !is_writable($file)) {
273
                $msg = "File specified in '$option' is not writable ($file)";
274
                throw new Exception\InvalidArgumentException($msg);
275
            }
276 28
        }
277
278
        // Step 4: Threads must be numeric greater than 0
279
280 28
        $threads = $config['threads'];
281
282 28
        if (!preg_match('/^([0-9])+$/', $threads) || $threads <= 0) {
283 1
            $msg = "Parameter 'threads' must be valid integer greater than 0";
284 1
            throw new Exception\InvalidArgumentException($msg);
285
        }
286
287
        // Step 5: Java must be callable
288
289
        // @todo, many options exists
290
291
        // Step 6: Check classpaths autoload
292 28
        if (isset($config['classpaths'])) {
293 28
            if (!is_array($config['classpaths'])) {
294 1
                $msg = "Option 'classpaths' mus be a php array.";
295 1
                throw new Exception\InvalidArgumentException($msg);
296
            }
297 28
            foreach ($config['classpaths'] as $classpath) {
298 27
                if (preg_match('/\*\.jar$/', $classpath)) {
299
                    // Check if directory exists
300 27
                    $directory = preg_replace('/\*\.jar$/', '', $classpath);
301 27
                    if (!is_dir($directory) || !is_readable($directory)) {
302 1
                        $msg = "Classpath error, the directory of '$classpath' does not exists or is not readable";
303 1
                        throw new Exception\InvalidArgumentException($msg);
304
                    }
305 27
                } elseif (preg_match('/\.jar$/', $classpath)) {
306
                    // Check if file exists
307 1
                    if (!is_file($classpath) || !is_readable($classpath)) {
308 1
                        $msg = "Classpath error, the file '$classpath' does not exists or is not readable";
309 1
                        throw new Exception\InvalidArgumentException($msg);
310
                    }
311
                } else {
312 1
                    $msg = "Error in classpath, files to import must end by .jar extension ($classpath)";
313 1
                    throw new Exception\InvalidArgumentException($msg);
314
                }
315 28
            }
316 28
        }
317 28
    }
318
}
319