ServletManager   B
last analyzed

Complexity

Total Complexity 45

Size/Duplication

Total Lines 470
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 9
Bugs 0 Features 0
Metric Value
eloc 63
c 9
b 0
f 0
dl 0
loc 470
ccs 0
cts 170
cp 0
rs 8.8
wmc 45

32 Methods

Rating   Name   Duplication   Size   Complexity  
A getErrorPages() 0 3 1
A hasSessionParameters() 0 3 1
A addSessionParameter() 0 3 1
A addInitParameter() 0 3 1
A getResourceLocator() 0 3 1
A injectServlets() 0 3 1
A addServlet() 0 3 1
A addErrorPage() 0 3 1
A getServlet() 0 4 2
A injectSessionParameters() 0 3 1
A injectInitParameters() 0 3 1
A getServletByMapping() 0 4 2
A addServletMapping() 0 3 1
A injectSecuredUrlConfigs() 0 3 1
A injectResourceLocator() 0 3 1
A getSessionParameter() 0 4 2
A injectErrorPages() 0 3 1
A getManagerSettings() 0 3 1
A getServlets() 0 3 1
A initialize() 0 11 1
A getServletLocator() 0 3 1
A locate() 0 16 3
A injectServletMappings() 0 3 1
A injectManagerSettings() 0 3 1
A getInitParameter() 0 4 2
A getServletMappings() 0 3 1
A getIdentifier() 0 3 1
A getSecuredUrlConfigs() 0 3 1
A registerServlet() 0 15 3
A lookup() 0 3 1
A registerServlets() 0 13 3
A postStartup() 0 33 4

How to fix   Complexity   

Complex Class

Complex classes like ServletManager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ServletManager, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * \AppserverIo\Appserver\ServletEngine\ServletManager
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/appserver
18
 * @link      http://www.appserver.io
19
 */
20
21
namespace AppserverIo\Appserver\ServletEngine;
22
23
use AppserverIo\Storage\GenericStackable;
24
use AppserverIo\Storage\StorageInterface;
25
use AppserverIo\Appserver\Core\AbstractEpbManager;
26
use AppserverIo\Psr\Di\ObjectManagerInterface;
27
use AppserverIo\Psr\Application\ApplicationInterface;
28
use AppserverIo\Psr\Servlet\ServletInterface;
29
use AppserverIo\Psr\Servlet\ServletContextInterface;
30
use AppserverIo\Psr\Servlet\Http\HttpServletRequestInterface;
31
use AppserverIo\Psr\Servlet\Description\ServletDescriptorInterface;
32
use AppserverIo\Appserver\Application\Interfaces\ManagerSettingsInterface;
33
use AppserverIo\Appserver\Application\Interfaces\ManagerSettingsAwareInterface;
34
35
/**
36
 * The servlet manager handles the servlets registered for the application.
37
 *
38
 * @author    Tim Wagner <[email protected]>
39
 * @copyright 2015 TechDivision GmbH <[email protected]>
40
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
41
 * @link      https://github.com/appserver-io/appserver
42
 * @link      http://www.appserver.io
43
 *
44
 * @property \AppserverIo\Storage\StorageInterface                                  $initParameters    The container for the init parameters
45
 * @property \AppserverIo\Appserver\ServletEngine\ResourceLocatorInterface          $resourceLocator   The resource locator for requested servlets
46
 * @property \AppserverIo\Appserver\ServletEngine\ResourceLocatorInterface          $servletLocator    The resource locator for the servlets
47
 * @property \AppserverIo\Storage\GenericStackable                                  $servletMappings   The container for the servlet mappings
48
 * @property \AppserverIo\Storage\StorageInterface                                  $servlets          The container for the servlets
49
 * @property \AppserverIo\Storage\StorageInterface                                  $sessionParameters The container for the session parameters
50
 * @property \AppserverIo\Appserver\Application\Interfaces\ManagerSettingsInterface $managerSettings   Settings for the servlet manager
51
 */
52
class ServletManager extends AbstractEpbManager implements ServletContextInterface, ManagerSettingsAwareInterface
53
{
54
55
    /**
56
     * Injects the resource locator that locates the requested servlet.
57
     *
58
     * @param \AppserverIo\Appserver\ServletEngine\ResourceLocatorInterface $resourceLocator The resource locator
59
     *
60
     * @return void
61
     */
62
    public function injectResourceLocator(ResourceLocatorInterface $resourceLocator)
63
    {
64
        $this->resourceLocator = $resourceLocator;
65
    }
66
67
    /**
68
     * Injects the container for the servlets.
69
     *
70
     * @param \AppserverIo\Storage\StorageInterface $servlets The container for the servlets
71
     *
72
     * @return void
73
     */
74
    public function injectServlets(StorageInterface $servlets)
75
    {
76
        $this->servlets = $servlets;
77
    }
78
79
    /**
80
     * Injects the container for the servlet mappings.
81
     *
82
     * @param \AppserverIo\Storage\GenericStackable $servletMappings The container for the servlet mappings
83
     *
84
     * @return void
85
     */
86
    public function injectServletMappings(GenericStackable $servletMappings)
87
    {
88
        $this->servletMappings = $servletMappings;
89
    }
90
91
    /**
92
     * Injects the container for the init parameters.
93
     *
94
     * @param \AppserverIo\Storage\StorageInterface $initParameters The container for the init parameters
95
     *
96
     * @return void
97
     */
98
    public function injectInitParameters(StorageInterface $initParameters)
99
    {
100
        $this->initParameters = $initParameters;
101
    }
102
103
    /**
104
     * Injects the container for the secured URL configurations.
105
     *
106
     * @param \AppserverIo\Storage\StorageInterface $securedUrlConfigs The container for the secured URL configurations
107
     *
108
     * @return void
109
     */
110
    public function injectSecuredUrlConfigs(StorageInterface $securedUrlConfigs)
111
    {
112
        $this->securedUrlConfigs = $securedUrlConfigs;
0 ignored issues
show
Bug Best Practice introduced by
The property securedUrlConfigs does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
113
    }
114
115
    /**
116
     * Injects the container for the session parameters.
117
     *
118
     * @param \AppserverIo\Storage\StorageInterface $sessionParameters The container for the session parameters
119
     *
120
     * @return void
121
     */
122
    public function injectSessionParameters(StorageInterface $sessionParameters)
123
    {
124
        $this->sessionParameters = $sessionParameters;
125
    }
126
127
    /**
128
     * Injects the container for the error page configuration.
129
     *
130
     * @param \AppserverIo\Storage\StorageInterface $errorPages The container for the error page configuration
131
     *
132
     * @return void
133
     */
134
    public function injectErrorPages(StorageInterface $errorPages)
135
    {
136
        $this->errorPages = $errorPages;
0 ignored issues
show
Bug Best Practice introduced by
The property errorPages does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
137
    }
138
139
    /**
140
     * Injects the servlet manager settings.
141
     *
142
     * @param \AppserverIo\Appserver\Application\Interfaces\ManagerSettingsInterface $managerSettings The servlet manager settings
143
     *
144
     * @return void
145
     */
146
    public function injectManagerSettings(ManagerSettingsInterface $managerSettings)
147
    {
148
        $this->managerSettings = $managerSettings;
149
    }
150
151
    /**
152
     * Has been automatically invoked by the container after the application
153
     * instance has been created.
154
     *
155
     * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application instance
156
     *
157
     * @return void
158
     * @see \AppserverIo\Psr\Application\ManagerInterface::initialize()
159
     */
160
    public function initialize(ApplicationInterface $application)
161
    {
162
163
        // register the annotation registries
164
        $application->registerAnnotationRegistries();
0 ignored issues
show
Bug introduced by
The method registerAnnotationRegistries() does not exist on AppserverIo\Psr\Application\ApplicationInterface. It seems like you code against a sub-type of AppserverIo\Psr\Application\ApplicationInterface such as AppserverIo\Appserver\Application\Application. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

164
        $application->/** @scrutinizer ignore-call */ 
165
                      registerAnnotationRegistries();
Loading history...
165
166
        // parse the object descriptors
167
        $this->parseObjectDescriptors();
168
169
        // register the servlets
170
        $this->registerServlets($application);
171
    }
172
173
    /**
174
     * Finds all servlets which are provided by the webapps and initializes them.
175
     *
176
     * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application instance
177
     *
178
     * @return void
179
     *
180
     * @throws \AppserverIo\Appserver\ServletEngine\InvalidServletMappingException
181
     */
182
    public function registerServlets(ApplicationInterface $application)
0 ignored issues
show
Unused Code introduced by
The parameter $application is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

182
    public function registerServlets(/** @scrutinizer ignore-unused */ ApplicationInterface $application)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
183
    {
184
185
        // load the object manager instance
186
        /** @var \AppserverIo\Psr\Di\ObjectManagerInterface $objectManager */
187
        $objectManager = $this->getApplication()->search(ObjectManagerInterface::IDENTIFIER);
188
189
        // register the beans located by annotations and the XML configuration
190
        /** \AppserverIo\Psr\Deployment\DescriptorInterface $objectDescriptor */
191
        foreach ($objectManager->getObjectDescriptors() as $descriptor) {
192
            // check if we've found a servlet descriptor and register the servlet
193
            if ($descriptor instanceof ServletDescriptorInterface) {
194
                $this->registerServlet($descriptor);
195
            }
196
        }
197
    }
198
199
    /**
200
     * Register the servlet described by the passed descriptor.
201
     *
202
     * @param \AppserverIo\Psr\Servlet\Description\ServletDescriptorInterface $descriptor The servlet descriptor
203
     *
204
     * @return void
205
     */
206
    public function registerServlet(ServletDescriptorInterface $descriptor)
207
    {
208
209
        try {
210
            // prepend the url-pattern - servlet mapping to the servlet mappings
211
            foreach ($descriptor->getUrlPatterns() as $pattern) {
212
                $this->addServletMapping($pattern, $descriptor->getName());
213
            }
214
215
            // register's the servlet's references
216
            $this->registerReferences($descriptor);
217
218
        } catch (\Exception $e) {
219
            // log the exception
220
            $this->getApplication()->getInitialContext()->getSystemLogger()->critical($e->__toString());
0 ignored issues
show
Bug introduced by
The method getInitialContext() does not exist on AppserverIo\Psr\Application\ApplicationInterface. It seems like you code against a sub-type of AppserverIo\Psr\Application\ApplicationInterface such as AppserverIo\Appserver\Application\Application. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

220
            $this->getApplication()->/** @scrutinizer ignore-call */ getInitialContext()->getSystemLogger()->critical($e->__toString());
Loading history...
221
        }
222
    }
223
224
    /**
225
     * Lifecycle callback that'll be invoked after the application has been started.
226
     *
227
     * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application instance
228
     *
229
     * @return void
230
     * @see \AppserverIo\Psr\Application\ManagerInterface::postStartup()
231
     */
232
    public function postStartup(ApplicationInterface $application)
233
    {
234
235
        // register the annotation registries
236
        $application->registerAnnotationRegistries();
237
238
        // load the object manager
239
        /** @var \AppserverIo\Psr\Di\ObjectManagerInterface $objectManager */
240
        $objectManager = $application->search(ObjectManagerInterface::IDENTIFIER);
241
242
        // register the beans found by annotations and the XML configuration
243
        /** \AppserverIo\Psr\Deployment\DescriptorInterface $objectDescriptor */
244
        foreach ($objectManager->getObjectDescriptors() as $descriptor) {
245
            // if we found a singleton session bean with a startup callback instanciate it
246
            if ($descriptor instanceof ServletDescriptorInterface) {
247
                // instantiate the servlet
248
                $instance = $this->get($servletName = $descriptor->getName());
249
250
                // initialize the servlet configuration
251
                $servletConfig = new ServletConfiguration();
252
                $servletConfig->injectServletContext($this);
253
                $servletConfig->injectServletName($servletName);
254
255
                // append the init params to the servlet configuration
256
                foreach ($descriptor->getInitParams() as $paramName => $paramValue) {
257
                    $servletConfig->addInitParameter($paramName, $paramValue);
258
                }
259
260
                // initialize the servlet
261
                $instance->init($servletConfig);
262
263
                // the servlet is added to the dictionary using the complete request path as the key
264
                $this->addServlet($servletName, $instance);
265
            }
266
        }
267
    }
268
269
    /**
270
     * Returns all servlets
271
     *
272
     * @return array The servlets collection
273
     */
274
    public function getServlets()
275
    {
276
        return $this->servlets;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->servlets returns the type AppserverIo\Storage\StorageInterface which is incompatible with the documented return type array.
Loading history...
277
    }
278
279
    /**
280
     * Returns the servlet mappings found in the
281
     * configuration file.
282
     *
283
     * @return \AppserverIo\Storage\GenericStackable The servlet mappings
284
     */
285
    public function getServletMappings()
286
    {
287
        return $this->servletMappings;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->servletMappings returns the type AppserverIo\Storage\GenericStackable which is incompatible with the return type mandated by AppserverIo\Psr\Servlet\...e::getServletMappings() of array.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
288
    }
289
290
    /**
291
     * Returns the resource locator for the servlets.
292
     *
293
     * @return \AppserverIo\Appserver\ServletEngine\ResourceLocatorInterface The resource locator for the servlets
294
     */
295
    public function getServletLocator()
296
    {
297
        return $this->servletLocator;
298
    }
299
300
    /**
301
     * Returns the servlet with the passed name.
302
     *
303
     * @param string $key The name of the servlet to return
304
     *
305
     * @return \AppserverIo\Psr\Servlet\ServletInterface The servlet instance
306
     */
307
    public function getServlet($key)
308
    {
309
        if ($this->servlets->has($key)) {
310
            return $this->servlets->get($key);
311
        }
312
    }
313
314
    /**
315
     * Returns the servlet for the passed URL mapping.
316
     *
317
     * @param string $urlMapping The URL mapping to return the servlet for
318
     *
319
     * @return \AppserverIo\Psr\Servlet\ServletInterface The servlet instance
320
     */
321
    public function getServletByMapping($urlMapping)
322
    {
323
        if (isset($this->servletMappings[$urlMapping])) {
324
            return $this->getServlet($this->servletMappings[$urlMapping]);
325
        }
326
    }
327
328
    /**
329
     * Registers a servlet under the passed key.
330
     *
331
     * @param string                                    $key     The servlet to key to register with
332
     * @param \AppserverIo\Psr\Servlet\ServletInterface $servlet The servlet to be registered
333
     *
334
     * @return void
335
     */
336
    public function addServlet($key, ServletInterface $servlet)
337
    {
338
        $this->servlets->set($key, $servlet);
339
    }
340
341
    /**
342
     * Adds an URL mapping for a servlet.
343
     *
344
     * @param string $pattern     The URL pattern we want the servlet to map to
345
     * @param string $servletName The servlet name to map
346
     *
347
     * @return void
348
     */
349
    public function addServletMapping($pattern, $servletName)
350
    {
351
        $this->servletMappings[$pattern] = $servletName;
352
    }
353
354
    /**
355
     * Return the resource locator instance.
356
     *
357
     * @return \AppserverIo\Appserver\ServletEngine\ResourceLocatorInterface The resource locator instance
358
     */
359
    public function getResourceLocator()
360
    {
361
        return $this->resourceLocator;
362
    }
363
364
    /**
365
     * Registers the init parameter under the passed name.
366
     *
367
     * @param string $name  Name to register the init parameter with
368
     * @param string $value The value of the init parameter
369
     *
370
     * @return void
371
     */
372
    public function addInitParameter($name, $value)
373
    {
374
        $this->initParameters->set($name, $value);
375
    }
376
377
    /**
378
     * Returns the init parameter with the passed name.
379
     *
380
     * @param string $name Name of the init parameter to return
381
     *
382
     * @return null|string
383
     */
384
    public function getInitParameter($name)
385
    {
386
        if ($this->initParameters->has($name)) {
387
            return $this->initParameters->get($name);
388
        }
389
    }
390
391
    /**
392
     * Registers the error page under the passed error code.
393
     *
394
     * @param string $errorCodePattern The error code for the page
395
     * @param string $errorLocation    The error page location
396
     *
397
     * @return void
398
     */
399
    public function addErrorPage($errorCodePattern, $errorLocation)
400
    {
401
        $this->errorPages->set($errorCodePattern, $errorLocation);
402
    }
403
404
    /**
405
     * Returns the container with the error page configuration.
406
     *
407
     * @return \AppserverIo\Storage\StorageInterface The container with the error page configuration
408
     */
409
    public function getErrorPages()
410
    {
411
        return $this->errorPages;
412
    }
413
414
    /**
415
     * Returns the webapps security context configurations.
416
     *
417
     * @return array The security context configurations
418
     * @throws \AppserverIo\Appserver\ServletEngine\OperationNotSupportedException Is thrown if this method has been invoked
419
     */
420
    public function getSecuredUrlConfigs()
421
    {
422
        throw new OperationNotSupportedException(sprintf('%s not yet implemented', __METHOD__));
423
    }
424
425
    /**
426
     * Registers the session parameter under the passed name.
427
     *
428
     * @param string $name  Name to register the session parameter with
429
     * @param string $value The value of the session parameter
430
     *
431
     * @return void
432
     */
433
    public function addSessionParameter($name, $value)
434
    {
435
        $this->sessionParameters->set($name, $value);
436
    }
437
438
    /**
439
     * Returns the session parameter with the passed name.
440
     *
441
     * @param string $name Name of the session parameter to return
442
     *
443
     * @return null|string
444
     */
445
    public function getSessionParameter($name)
446
    {
447
        if ($this->sessionParameters->has($name)) {
448
            return $this->sessionParameters->get($name);
449
        }
450
    }
451
452
    /**
453
     * Returns TRUE if we've at least one session parameter configured, else FALSE.
454
     *
455
     * @return boolean TRUE if we've at least one session parameter configured, else FALSE
456
     */
457
    public function hasSessionParameters()
458
    {
459
        return sizeof($this->sessionParameters) > 0;
0 ignored issues
show
Bug introduced by
$this->sessionParameters of type AppserverIo\Storage\StorageInterface is incompatible with the type Countable|array expected by parameter $var of sizeof(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

459
        return sizeof(/** @scrutinizer ignore-type */ $this->sessionParameters) > 0;
Loading history...
460
    }
461
462
    /**
463
     * Return's the servlet manager settings.
464
     *
465
     * @return \AppserverIo\Appserver\Application\Interfaces\ManagerSettingsInterface The servlet manager settings
466
     */
467
    public function getManagerSettings()
468
    {
469
        return $this->managerSettings;
470
    }
471
472
    /**
473
     * Tries to locate the resource related with the request.
474
     *
475
     * @param \AppserverIo\Psr\Servlet\Http\HttpServletRequestInterface $servletRequest The request instance to return the servlet for
476
     * @param array                                                     $args           The arguments passed to the servlet constructor
477
     *
478
     * @return \AppserverIo\Psr\Servlet\ServletInterface The requested servlet
479
     * @see \AppserverIo\Appserver\ServletEngine\ServletLocator::locate()
480
     */
481
    public function locate(HttpServletRequestInterface $servletRequest, array $args = array())
482
    {
483
484
        // load the servlet path => to locate the servlet
485
        $servletPath = $servletRequest->getServletPath();
486
487
        // if a session cookie has been sent, initialize the session manager and the session
488
        if ($manager = $this->getApplication()->search(SessionManagerInterface::IDENTIFIER)) {
489
            $requestedSessionName = $manager->getSessionSettings()->getSessionName();
490
            if ($servletRequest->hasCookie($requestedSessionName)) {
491
                $servletRequest->getCookie($requestedSessionName)->getValue();
492
            }
493
        }
494
495
        // return the instance
496
        return $this->lookup($servletPath, $args);
497
    }
498
499
    /**
500
     * Runs a lookup for the servlet with the passed class name and
501
     * session ID.
502
     *
503
     * @param string $servletPath The servlet path
504
     * @param array  $args        The arguments passed to the servlet constructor
505
     *
506
     * @return \AppserverIo\Psr\Servlet\ServletInterface The requested servlet
507
     */
508
    public function lookup($servletPath, array $args = array())
509
    {
510
        return $this->getResourceLocator()->locate($this, $servletPath, $args);
0 ignored issues
show
Unused Code introduced by
The call to AppserverIo\Appserver\Se...atorInterface::locate() has too many arguments starting with $args. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

510
        return $this->getResourceLocator()->/** @scrutinizer ignore-call */ locate($this, $servletPath, $args);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
511
    }
512
513
    /**
514
     * Returns the identifier for the servlet manager instance.
515
     *
516
     * @return string
517
     * @see \AppserverIo\Psr\Application\ManagerInterface::getIdentifier()
518
     */
519
    public function getIdentifier()
520
    {
521
        return ServletContextInterface::IDENTIFIER;
522
    }
523
}
524