RemoteContextConnection::getAppName()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

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
nc 1
nop 0
crap 1
1
<?php
2
3
/**
4
 * AppserverIo\RemoteMethodInvocation\RemoteContextConnection
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/rmi
18
 * @link      http://www.appserver.io
19
 */
20
21
namespace AppserverIo\RemoteMethodInvocation;
22
23
use AppserverIo\Collections\CollectionInterface;
24
25
/**
26
 * Connection implementation to invoke a remote method call over a socket.
27
 *
28
 * @author    Tim Wagner <[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/rmi
32
 * @link      http://www.appserver.io
33
 */
34
class RemoteContextConnection implements ConnectionInterface
35
{
36
37
    /**
38
     * The default transport to use.
39
     *
40
     * @var string
41
     */
42
    const DEFAULT_SCHEME = 'http';
43
44
    /**
45
     * The default client sockets IP address.
46
     *
47
     * @var string
48
     */
49
    const DEFAULT_HOST = '127.0.0.1';
50
51
    /**
52
     * The default client sockets port.
53
     *
54
     * @var integer
55
     */
56
    const DEFAULT_PORT = 8585;
57
58
    /**
59
     * The default transport to use.
60
     *
61
     * @var string
62
     */
63
    protected $transport = RemoteContextConnection::DEFAULT_SCHEME;
64
65
    /**
66
     * The client socket's IP address.
67
     *
68
     * @var string
69
     */
70
    protected $address = RemoteContextConnection::DEFAULT_HOST;
71
72
    /**
73
     * The client socket's port.
74
     *
75
     * @var integer
76
     */
77
    protected $port = RemoteContextConnection::DEFAULT_PORT;
78
79
    /**
80
     * The name of the webapp using this client connection.
81
     *
82
     * @var string
83
     */
84
    protected $appName;
85
86
    /**
87
     * The storage for the sessions.
88
     *
89
     * @var \AppserverIo\Collections\CollectionInterface
90
     */
91
    protected $sessions = null;
92
93
    /**
94
     * Parser to process the remote method call.
95
     *
96
     * @var \AppserverIo\RemoteMethodInvocation\RemoteMethodCallParser
97
     */
98
    protected $parser;
99
100
    /**
101
     * Injects the collection for the sessions.
102
     *
103
     * @param \AppserverIo\Collections\CollectionInterface $sessions The collection for the sessions
104
     *
105
     * @return void
106
     */
107
    public function injectSessions(CollectionInterface $sessions)
108
    {
109
        $this->sessions = $sessions;
110
    }
111
112
    /**
113
     * Returns the collection with the sessions.
114
     *
115
     * @return \AppserverIo\Collections\CollectionInterface The collection with the sessions
116
     */
117
    public function getSessions()
118
    {
119
        return $this->sessions;
120
    }
121
122
    /**
123
     * Injects the remote method call parser.
124
     *
125
     * @param \AppserverIo\RemoteMethodInvocation\RemoteMethodCallParser $parser The remote method call parser
126
     *
127
     * @return void
128
     */
129
    public function injectParser(RemoteMethodCallParser $parser)
130
    {
131
        $this->parser = $parser;
132
    }
133
134
    /**
135
     * Returns the parser to process the remote method call.
136
     *
137
     * @return \AppserverIo\RemoteMethodInvocation\RemoteMethodCallParser The parser instance
138
     */
139
    public function getParser()
140
    {
141
        return $this->parser;
142
    }
143
144
    /**
145
     * Sets the clients webapp name
146
     *
147
     * @param string $appName Name of the webapp using this client connection
148
     *
149
     * @return void
150
     */
151 1
    public function injectAppName($appName)
152
    {
153 1
        $this->appName = $appName;
154 1
    }
155
156
    /**
157
     * Returns the name of the webapp this connection is for
158
     *
159
     * @return string The webapp name
160
     */
161 1
    public function getAppName()
162
    {
163 1
        return $this->appName;
164
    }
165
166
    /**
167
     * Sets the servers IP address for the client to connect to.
168
     *
169
     * @param string $address The servers IP address to connect to
170
     *
171
     * @return void
172
     */
173 1
    public function injectAddress($address)
174
    {
175 1
        $this->address = $address;
176 1
    }
177
178
    /**
179
     * Returns the client sockets IP address.
180
     *
181
     * @return string
182
     */
183 1
    public function getAddress()
184
    {
185 1
        return $this->address;
186
    }
187
188
    /**
189
     *  Sets  the servers port for the client to connect to.
190
     *
191
     * @param integer $port The servers port to connect to
192
     *
193
     * @return void
194
     */
195 1
    public function injectPort($port)
196
    {
197 1
        $this->port = $port;
198 1
    }
199
200
    /**
201
     * Returns the client port.
202
     *
203
     * @return integer The client port
204
     */
205 1
    public function getPort()
206
    {
207 1
        return $this->port;
208
    }
209
210
    /**
211
     *  Sets the transport to use.
212
     *
213
     * @param integer $transport The transport to use
214
     *
215
     * @return void
216
     */
217
    public function injectTransport($transport)
218
    {
219
        $this->transport = $transport;
0 ignored issues
show
Documentation Bug introduced by
The property $transport was declared of type string, but $transport is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
220
    }
221
222
    /**
223
     * Returns the transport to use.
224
     *
225
     * @return integer The transport to use.
226
     */
227
    public function getTransport()
228
    {
229
        return $this->transport;
230
    }
231
232
    /**
233
     * Creates the connection to the container.
234
     *
235
     * @return void
236
     */
237
    public function connect()
238
    {
239
        return;
240
    }
241
242
    /**
243
     * Shutdown the connection to the container.
244
     *
245
     * @return void
246
     */
247
    public function disconnect()
248
    {
249
        return;
250
    }
251
252
    /**
253
     * Returns the socket the connection is based on.
254
     *
255
     * @return object|null The socket instance
256
     */
257
    public function getSocket()
258
    {
259
        return;
260
    }
261
262
    /**
263
     * Sends the remote method call to the container instance.
264
     *
265
     * @param \AppserverIo\RemoteMethodInvocation\RemoteMethodInterface $remoteMethod The remote method instance
266
     *
267
     * @return mixed The response from the container
268
     * @see \AppserverIo\RemoteMethodInvocation\ConnectionInterface::send()
269
     *
270
     * @throws \Exception Is thrown, if the remote method call cannot be invoked
271
     */
272
    public function send(RemoteMethodInterface $remoteMethod)
273
    {
274
275
        // set address + port + appName
276
        $remoteMethod->setAddress($this->getAddress());
277
        $remoteMethod->setPort($this->getPort());
278
        $remoteMethod->setAppName($this->getAppName());
279
280
        // serialize the remote method and write it to the socket
281
        $packed = RemoteMethodProtocol::pack($remoteMethod);
282
283
        // performs the HTTP POST
284
        $opts = array (
285
            "http" => array (
286
                "method"  => "POST",
287
                "header"  => sprintf("Content-Type: text/plain\r\nCookie: %s=%s\r\n", SessionInterface::SESSION_NAME, $remoteMethod->getSessionId()),
288
                "content" => $packed
289
            )
290
        );
291
292
        // create the context
293
        $context  = stream_context_create($opts);
294
295
        // invoke a HTTP request and try to read the response from the remote server
296
        if ($fp = fopen($url = $this->getBaseUrl($this->getPath()), 'r', false, $context)) {
297
            // initialize the response
298
            $response = '';
299
            // read while content is available
300
            while ($row = fgets($fp)) {
301
                $response .= trim($row);
302
            }
303
        } else {
304
            throw new \Exception('Unable to connect to ' . $url);
305
        }
306
307
        // read the remote method call result
308
        $result = RemoteMethodProtocol::unpack($response);
309
310
        // if an exception returns, throw it again
311
        if ($result instanceof RemoteExceptionWrapper) {
312
            throw $result->toException();
313
        }
314
315
        // close the connection and return the data
316
        return $result;
317
    }
318
319
    /**
320
     * Prepares path for the connection to the persistence container.
321
     *
322
     * @return string The path to define the persistence container module
323
     */
324
    protected function getPath()
325
    {
326
        return '/' . $this->getAppName() . '/index.pc';
327
    }
328
329
    /**
330
     * Prepares the base URL we used for the connection to the persistence container.
331
     *
332
     * @param string $path The URL path to append
333
     *
334
     * @return string The default base URL
335
     */
336
    protected function getBaseUrl($path = '')
337
    {
338
        // initialize the requested URL with the default connection values
339
        return $this->getTransport() . '://' . $this->getAddress() . ':' . $this->getPort() . $path;
340
    }
341
342
    /**
343
     * Initializes a new session instance.
344
     *
345
     * @return \AppserverIo\RemoteMethodInvocation\SessionInterface The session instance
346
     * @see \AppserverIo\RemoteMethodInvocation\ConnectionInterface::createContextSession()
347
     */
348
    public function createContextSession()
349
    {
350
        $this->sessions->add($session = new ContextSession($this));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface AppserverIo\Collections\CollectionInterface as the method add() does only exist in the following implementations of said interface: AppserverIo\Collections\ArrayList, AppserverIo\Collections\Dictionary, AppserverIo\Collections\HashMap, AppserverIo\Collections\IdentityDictionary, AppserverIo\Collections\TreeMap, AppserverIo\RemoteMethodInvocation\ContextSession.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
351
        return $session;
352
    }
353
354
    /**
355
     * Returns the application instance.
356
     *
357
     * @return \AppserverIo\Psr\Application\ApplicationInterface|null The application instance
358
     */
359
    public function getApplication()
360
    {
361
        return;
362
    }
363
}
364