Completed
Push — master ( 8e8e12...cf4981 )
by Sébastien
04:15
created

Config::getBaseDir()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2.0625

Importance

Changes 0
Metric Value
dl 0
loc 12
c 0
b 0
f 0
ccs 6
cts 8
cp 0.75
rs 9.4285
cc 2
eloc 8
nc 2
nop 0
crap 2.0625
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
    /**
23
     * Default configuration options
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
     * @var array
38
     */
39
    protected $config;
40
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
     * @param array $config
71
     *
72
     */
73 30
    public function __construct(array $config)
74
    {
75 30
        if (!isset($config['port'])) {
76 3
            throw new Exception\InvalidArgumentException("Error missing required 'port' in config");
77 27
        } 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 26
        $config = array_merge($this->getDefaultConfig($config['port']), $config);
81 26
        $this->checkConfig($config);
82 25
        $this->config = $config;
83 25
    }
84
85
    /**
86
     * Return port on which standalone server listens
87
     * @return int
88
     */
89 18
    public function getPort()
90
    {
91 18
        return $this->config['port'];
92
    }
93
94
    /**
95
     * Return jar file of the server
96
     * @return string
97
     */
98 18
    public function getServerJar()
99
    {
100 18
        return $this->config['server_jar'];
101
    }
102
103
104
    /**
105
     * Return java binary
106
     * @return string
107
     */
108 18
    public function getJavaBin()
109
    {
110 18
        return $this->config['java_bin'];
111
    }
112
113
    /**
114
     * Return log file
115
     * @return string
116
     */
117 18
    public function getLogFile()
118
    {
119 18
        return $this->config['log_file'];
120
    }
121
122
    /**
123
     * Return an array containing the java classpath(s) for the server
124
     * @return array
125
     */
126 18
    public function getClasspaths()
127
    {
128 18
        return $this->config['classpaths'];
129
    }
130
131
    /**
132
     * Return pid file where to store process id
133
     * @return string
134
     */
135 20
    public function getPidFile()
136
    {
137 20
        return $this->config['pid_file'];
138
    }
139
140
141
    /**
142
     * Return standalone server threads
143
     *
144
     * @return int|string
145
     */
146 15
    public function getThreads()
147
    {
148 15
        return $this->config['threads'];
149
    }
150
151
    /**
152
     * Return standalone configuration
153
     *
154
     * @return array
155
     */
156 4
    public function getConfig()
157
    {
158 4
        return $this->config;
159
    }
160
161
    /**
162
     * Return default configuration options
163
     * @param int $port
164
     * @return array
165
     */
166 26
    protected function getDefaultConfig($port)
167
    {
168 26
        $base_dir = $this->getBaseDir();
169 26
        $config = [];
170 26
        foreach ($this->default_config as $key => $value) {
171 26
            $tmp = str_replace('{base_dir}', $base_dir, $value);
172 26
            $tmp = str_replace('{tcp_port}', $port, $tmp);
173 26
            $config[$key] = $tmp;
174 26
        }
175 26
        return $config;
176
    }
177
178
    /**
179
     * Return pjbserver-tools installation base directory
180
     *
181
     * @throws Exception\RuntimeException
182
     * @return string
183
     */
184 26
    public function getBaseDir()
185
    {
186
        // Four levels back.
187 26
        $ds  = DIRECTORY_SEPARATOR;
188 26
        $dir = __DIR__ . "$ds..$ds..$ds..$ds..$ds";
189 26
        $base_dir = realpath($dir);
190 26
        if (!$base_dir) {
191
            $message = "Cannot resolve project base directory.";
192
            throw new Exception\RuntimeException($message);
193
        }
194 26
        return $base_dir;
195
    }
196
197
    /**
198
     * Check configuration parameters
199
     * @throws Exception\InvalidArgumentException
200
     * @param array $config
201
     */
202 26
    protected function checkConfig(array $config)
203
    {
204
        // Step 1: all required options
205 26
        $required = ['port', 'server_jar', 'log_file', 'pid_file', 'threads'];
206 26
        foreach ($required as $option) {
207 26
            if (!isset($config[$option]) || $config[$option] == '') {
208
                throw new Exception\InvalidArgumentException("Missing resuired configuration option: '$option''");
209
            }
210 26
        }
211
212
        // Step 2: server_jar file must exists
213 26
        if (!is_file($config['server_jar']) || !is_readable($config['server_jar'])) {
214 1
            throw new Exception\InvalidArgumentException("Server jar file not exists or unreadable. server-jar: '" . $config['server_jar'] ."'");
215
        }
216
217
        // Step 3: log and pid file should be creatable
218 25
        $temp_required_files = ['log_file', 'pid_file'];
219 25
        foreach ($temp_required_files as $option) {
220 25
            $file = $config[$option];
221 25
            $info = pathinfo($file);
222 25
            $dirname = $info['dirname'];
223 25
            if (!is_dir($dirname) || $dirname == ".") {
224
                $msg = "Option '$option' refer to an invalid or non-existent directory ($file)";
225
                throw new Exception\InvalidArgumentException($msg);
226
            }
227 25
            if (is_dir($file)) {
228
                $msg = "Option '$option' does not refer to a file but an existing directory ($file)";
229
                throw new Exception\InvalidArgumentException($msg);
230
            }
231 25
            if (file_exists($file) && !is_writable($file)) {
232
                $msg = "File specified in '$option' is not writable ($file)";
233
                throw new Exception\InvalidArgumentException($msg);
234
            }
235 25
        }
236
237
        // Step 4: Threads must be numeric greater than 0
238
239 25
        $threads = $config['threads'];
240
241 25
        if (!preg_match('/^([0-9])+$/', $threads) || $threads <= 0) {
242 1
            $msg = "Parameter 'threads' must be valid integer greater than 0";
243 1
            throw new Exception\InvalidArgumentException($msg);
244
        }
245
246
        // Step 5: Java must be callable
247
248
        // @todo, many options exists
249
250
        // Step 6: Check classpaths autoload
251 25
        if (isset($config['classpaths'])) {
252 25
            if (!is_array($config['classpaths'])) {
253 1
                $msg = "Option 'classpaths' mus be a php array.";
254 1
                throw new Exception\InvalidArgumentException($msg);
255
            }
256 25
            foreach ($config['classpaths'] as $classpath) {
257 25
                if (preg_match('/\*\.jar$/', $classpath)) {
258
                    // Check if directory exists
259 25
                    $directory = preg_replace('/\*\.jar$/', '', $classpath);
260 25
                    if (!is_dir($directory) || !is_readable($directory)) {
261 1
                        $msg = "Classpath error, the directory of '$classpath' does not exists or is not readable";
262 1
                        throw new Exception\InvalidArgumentException($msg);
263
                    }
264 25
                } elseif (preg_match('/\.jar$/', $classpath)) {
265
                    // Check if file exists
266 1
                    if (!is_file($classpath) || !is_readable($classpath)) {
267 1
                        $msg = "Classpath error, the file '$classpath' does not exists or is not readable";
268 1
                        throw new Exception\InvalidArgumentException($msg);
269
                    }
270
                } else {
271 1
                    $msg = "Error in classpath, files to import must end by .jar extension ($classpath)";
272 1
                    throw new Exception\InvalidArgumentException($msg);
273
                }
274 25
            }
275 25
        }
276 25
    }
277
}
278