Completed
Pull Request — master (#1105)
by Tim
42:55
created

ServletManager::postStartup()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 30
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 11
nc 4
nop 1
dl 0
loc 30
ccs 0
cts 16
cp 0
crap 20
rs 9.9
c 0
b 0
f 0
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\ServletEngine\DependencyInjection\DirectoryParser;
33
use AppserverIo\Appserver\ServletEngine\DependencyInjection\DeploymentDescriptorParser;
34
use AppserverIo\Appserver\Application\Interfaces\ManagerSettingsInterface;
35
use AppserverIo\Appserver\Application\Interfaces\ManagerSettingsAwareInterface;
36
37
/**
38
 * The servlet manager handles the servlets registered for the application.
39
 *
40
 * @author    Tim Wagner <[email protected]>
41
 * @copyright 2015 TechDivision GmbH <[email protected]>
42
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
43
 * @link      https://github.com/appserver-io/appserver
44
 * @link      http://www.appserver.io
45
 *
46
 * @property array                                                                  $directories       The additional directories to be parsed
47
 * @property \AppserverIo\Storage\StorageInterface                                  $initParameters    The container for the init parameters
48
 * @property \AppserverIo\Appserver\ServletEngine\ResourceLocatorInterface          $resourceLocator   The resource locator for requested servlets
49
 * @property \AppserverIo\Appserver\ServletEngine\ResourceLocatorInterface          $servletLocator    The resource locator for the servlets
50
 * @property \AppserverIo\Storage\GenericStackable                                  $servletMappings   The container for the servlet mappings
51
 * @property \AppserverIo\Storage\StorageInterface                                  $servlets          The container for the servlets
52
 * @property \AppserverIo\Storage\StorageInterface                                  $sessionParameters The container for the session parameters
53
 * @property \AppserverIo\Appserver\Application\Interfaces\ManagerSettingsInterface $managerSettings   Settings for the servlet manager
54
 */
55
class ServletManager extends AbstractEpbManager implements ServletContextInterface, ManagerSettingsAwareInterface
56
{
57
58
    /**
59
     * Injects the additional directories to be parsed when looking for servlets.
60
     *
61
     * @param array $directories The additional directories to be parsed
62
     *
63
     * @return void
64
     */
65
    public function injectDirectories(array $directories)
66
    {
67
        $this->directories = $directories;
68
    }
69
70
    /**
71
     * Injects the resource locator that locates the requested servlet.
72
     *
73
     * @param \AppserverIo\Appserver\ServletEngine\ResourceLocatorInterface $resourceLocator The resource locator
74
     *
75
     * @return void
76
     */
77
    public function injectResourceLocator(ResourceLocatorInterface $resourceLocator)
78
    {
79
        $this->resourceLocator = $resourceLocator;
80
    }
81
82
    /**
83
     * Injects the container for the servlets.
84
     *
85
     * @param \AppserverIo\Storage\StorageInterface $servlets The container for the servlets
86
     *
87
     * @return void
88
     */
89
    public function injectServlets(StorageInterface $servlets)
90
    {
91
        $this->servlets = $servlets;
92
    }
93
94
    /**
95
     * Injects the container for the servlet mappings.
96
     *
97
     * @param \AppserverIo\Storage\GenericStackable $servletMappings The container for the servlet mappings
98
     *
99
     * @return void
100
     */
101
    public function injectServletMappings(GenericStackable $servletMappings)
102
    {
103
        $this->servletMappings = $servletMappings;
104
    }
105
106
    /**
107
     * Injects the container for the init parameters.
108
     *
109
     * @param \AppserverIo\Storage\StorageInterface $initParameters The container for the init parameters
110
     *
111
     * @return void
112
     */
113
    public function injectInitParameters(StorageInterface $initParameters)
114
    {
115
        $this->initParameters = $initParameters;
116
    }
117
118
    /**
119
     * Injects the container for the secured URL configurations.
120
     *
121
     * @param \AppserverIo\Storage\StorageInterface $securedUrlConfigs The container for the secured URL configurations
122
     *
123
     * @return void
124
     */
125
    public function injectSecuredUrlConfigs(StorageInterface $securedUrlConfigs)
126
    {
127
        $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...
128
    }
129
130
    /**
131
     * Injects the container for the session parameters.
132
     *
133
     * @param \AppserverIo\Storage\StorageInterface $sessionParameters The container for the session parameters
134
     *
135
     * @return void
136
     */
137
    public function injectSessionParameters(StorageInterface $sessionParameters)
138
    {
139
        $this->sessionParameters = $sessionParameters;
140
    }
141
142
    /**
143
     * Injects the container for the error page configuration.
144
     *
145
     * @param \AppserverIo\Storage\StorageInterface $errorPages The container for the error page configuration
146
     *
147
     * @return void
148
     */
149
    public function injectErrorPages(StorageInterface $errorPages)
150
    {
151
        $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...
152
    }
153
154
    /**
155
     * Injects the servlet manager settings.
156
     *
157
     * @param \AppserverIo\Appserver\Application\Interfaces\ManagerSettingsInterface $managerSettings The servlet manager settings
158
     *
159
     * @return void
160
     */
161
    public function injectManagerSettings(ManagerSettingsInterface $managerSettings)
162
    {
163
        $this->managerSettings = $managerSettings;
164
    }
165
166
    /**
167
     * Has been automatically invoked by the container after the application
168
     * instance has been created.
169
     *
170
     * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application instance
171
     *
172
     * @return void
173
     * @see \AppserverIo\Psr\Application\ManagerInterface::initialize()
174
     */
175
    public function initialize(ApplicationInterface $application)
176
    {
177
        $this->registerServlets($application);
178
    }
179
180
    /**
181
     * Finds all servlets which are provided by the webapps and initializes them.
182
     *
183
     * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application instance
184
     *
185
     * @return void
186
     *
187
     * @throws \AppserverIo\Appserver\ServletEngine\InvalidServletMappingException
188
     */
189
    public function registerServlets(ApplicationInterface $application)
190
    {
191
192
        // query whether or not the web application folder exists
193
        if (is_dir($this->getWebappPath()) === false) {
194
            return;
195
        }
196
197
        // register the annotation registries
198
        $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

198
        $application->/** @scrutinizer ignore-call */ 
199
                      registerAnnotationRegistries();
Loading history...
199
200
        // initialize the directory parser and parse the web application's base directory for annotated servlets
201
        $directoryParser = new DirectoryParser();
202
        $directoryParser->injectServletContext($this);
203
        $directoryParser->parse();
204
205
        // initialize the deployment descriptor parser and parse the web application's deployment descriptor for servlets
206
        $deploymentDescriptorParser = new DeploymentDescriptorParser();
207
        $deploymentDescriptorParser->injectServletContext($this);
208
        $deploymentDescriptorParser->parse();
209
210
        // load the object manager instance
211
        /** @var \AppserverIo\Psr\Di\ObjectManagerInterface $objectManager */
212
        $objectManager = $this->getApplication()->search(ObjectManagerInterface::IDENTIFIER);
213
214
        // register the beans located by annotations and the XML configuration
215
        /** \AppserverIo\Psr\Deployment\DescriptorInterface $objectDescriptor */
216
        foreach ($objectManager->getObjectDescriptors() as $descriptor) {
217
            // check if we've found a servlet descriptor and register the servlet
218
            if ($descriptor instanceof ServletDescriptorInterface) {
219
                $this->registerServlet($descriptor);
220
            }
221
        }
222
    }
223
224
    /**
225
     * Register the servlet described by the passed descriptor.
226
     *
227
     * @param \AppserverIo\Psr\Servlet\Description\ServletDescriptorInterface $descriptor The servlet descriptor
228
     *
229
     * @return void
230
     */
231
    public function registerServlet(ServletDescriptorInterface $descriptor)
232
    {
233
234
        try {
235
            // prepend the url-pattern - servlet mapping to the servlet mappings
236
            foreach ($descriptor->getUrlPatterns() as $pattern) {
237
                $this->addServletMapping($pattern, $descriptor->getName());
238
            }
239
240
            // register's the servlet's references
241
            $this->registerReferences($descriptor);
242
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
243
        } catch (\Exception $e) {
244
            // log the exception
245
            $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

245
            $this->getApplication()->/** @scrutinizer ignore-call */ getInitialContext()->getSystemLogger()->critical($e->__toString());
Loading history...
246
        }
247
    }
248
249
    /**
250
     * Lifecycle callback that'll be invoked after the application has been started.
251
     *
252
     * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application instance
253
     *
254
     * @return void
255
     * @see \AppserverIo\Psr\Application\ManagerInterface::postStartup()
256
     */
257
    public function postStartup(ApplicationInterface $application)
258
    {
259
260
        // load the object manager
261
        /** @var \AppserverIo\Psr\Di\ObjectManagerInterface $objectManager */
262
        $objectManager = $application->search(ObjectManagerInterface::IDENTIFIER);
263
264
        // register the beans found by annotations and the XML configuration
265
        /** \AppserverIo\Psr\Deployment\DescriptorInterface $objectDescriptor */
266
        foreach ($objectManager->getObjectDescriptors() as $descriptor) {
267
            // if we found a singleton session bean with a startup callback instanciate it
268
            if ($descriptor instanceof ServletDescriptorInterface) {
269
                // instantiate the servlet
270
                $instance = $this->get($servletName = $descriptor->getName());
271
272
                // initialize the servlet configuration
273
                $servletConfig = new ServletConfiguration();
274
                $servletConfig->injectServletContext($this);
275
                $servletConfig->injectServletName($servletName);
276
277
                // append the init params to the servlet configuration
278
                foreach ($descriptor->getInitParams() as $paramName => $paramValue) {
279
                    $servletConfig->addInitParameter($paramName, $paramValue);
280
                }
281
282
                // initialize the servlet
283
                $instance->init($servletConfig);
284
285
                // the servlet is added to the dictionary using the complete request path as the key
286
                $this->addServlet($servletName, $instance);
287
            }
288
        }
289
    }
290
291
    /**
292
     * Returns all the additional directories to be parsed for servlets.
293
     *
294
     * @return array The additional directories
295
     */
296
    public function getDirectories()
297
    {
298
        return $this->directories;
299
    }
300
301
    /**
302
     * Returns all servlets
303
     *
304
     * @return array The servlets collection
305
     */
306
    public function getServlets()
307
    {
308
        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...
309
    }
310
311
    /**
312
     * Returns the servlet mappings found in the
313
     * configuration file.
314
     *
315
     * @return \AppserverIo\Storage\GenericStackable The servlet mappings
316
     */
317
    public function getServletMappings()
318
    {
319
        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...
320
    }
321
322
    /**
323
     * Returns the resource locator for the servlets.
324
     *
325
     * @return \AppserverIo\Appserver\ServletEngine\ResourceLocatorInterface The resource locator for the servlets
326
     */
327
    public function getServletLocator()
328
    {
329
        return $this->servletLocator;
330
    }
331
332
    /**
333
     * Returns the servlet with the passed name.
334
     *
335
     * @param string $key The name of the servlet to return
336
     *
337
     * @return \AppserverIo\Psr\Servlet\ServletInterface The servlet instance
338
     */
339
    public function getServlet($key)
340
    {
341
        if ($this->servlets->has($key)) {
342
            return $this->servlets->get($key);
343
        }
344
    }
345
346
    /**
347
     * Returns the servlet for the passed URL mapping.
348
     *
349
     * @param string $urlMapping The URL mapping to return the servlet for
350
     *
351
     * @return \AppserverIo\Psr\Servlet\ServletInterface The servlet instance
352
     */
353
    public function getServletByMapping($urlMapping)
354
    {
355
        if (isset($this->servletMappings[$urlMapping])) {
356
            return $this->getServlet($this->servletMappings[$urlMapping]);
357
        }
358
    }
359
360
    /**
361
     * Registers a servlet under the passed key.
362
     *
363
     * @param string                                    $key     The servlet to key to register with
364
     * @param \AppserverIo\Psr\Servlet\ServletInterface $servlet The servlet to be registered
365
     *
366
     * @return void
367
     */
368
    public function addServlet($key, ServletInterface $servlet)
369
    {
370
        $this->servlets->set($key, $servlet);
371
    }
372
373
    /**
374
     * Adds an URL mapping for a servlet.
375
     *
376
     * @param string $pattern     The URL pattern we want the servlet to map to
377
     * @param string $servletName The servlet name to map
378
     *
379
     * @return void
380
     */
381
    public function addServletMapping($pattern, $servletName)
382
    {
383
        $this->servletMappings[$pattern] = $servletName;
384
    }
385
386
    /**
387
     * Return the resource locator instance.
388
     *
389
     * @return \AppserverIo\Appserver\ServletEngine\ResourceLocatorInterface The resource locator instance
390
     */
391
    public function getResourceLocator()
392
    {
393
        return $this->resourceLocator;
394
    }
395
396
    /**
397
     * Registers the init parameter under the passed name.
398
     *
399
     * @param string $name  Name to register the init parameter with
400
     * @param string $value The value of the init parameter
401
     *
402
     * @return void
403
     */
404
    public function addInitParameter($name, $value)
405
    {
406
        $this->initParameters->set($name, $value);
407
    }
408
409
    /**
410
     * Returns the init parameter with the passed name.
411
     *
412
     * @param string $name Name of the init parameter to return
413
     *
414
     * @return null|string
415
     */
416
    public function getInitParameter($name)
417
    {
418
        if ($this->initParameters->has($name)) {
419
            return $this->initParameters->get($name);
420
        }
421
    }
422
423
    /**
424
     * Registers the error page under the passed error code.
425
     *
426
     * @param string $errorCodePattern The error code for the page
427
     * @param string $errorLocation    The error page location
428
     *
429
     * @return void
430
     */
431
    public function addErrorPage($errorCodePattern, $errorLocation)
432
    {
433
        $this->errorPages->set($errorCodePattern, $errorLocation);
434
    }
435
436
    /**
437
     * Returns the container with the error page configuration.
438
     *
439
     * @return \AppserverIo\Storage\StorageInterface The container with the error page configuration
440
     */
441
    public function getErrorPages()
442
    {
443
        return $this->errorPages;
444
    }
445
446
    /**
447
     * Returns the webapps security context configurations.
448
     *
449
     * @return array The security context configurations
450
     * @throws \AppserverIo\Appserver\ServletEngine\OperationNotSupportedException Is thrown if this method has been invoked
451
     */
452
    public function getSecuredUrlConfigs()
453
    {
454
        throw new OperationNotSupportedException(sprintf('%s not yet implemented', __METHOD__));
455
    }
456
457
    /**
458
     * Registers the session parameter under the passed name.
459
     *
460
     * @param string $name  Name to register the session parameter with
461
     * @param string $value The value of the session parameter
462
     *
463
     * @return void
464
     */
465
    public function addSessionParameter($name, $value)
466
    {
467
        $this->sessionParameters->set($name, $value);
468
    }
469
470
    /**
471
     * Returns the session parameter with the passed name.
472
     *
473
     * @param string $name Name of the session parameter to return
474
     *
475
     * @return null|string
476
     */
477
    public function getSessionParameter($name)
478
    {
479
        if ($this->sessionParameters->has($name)) {
480
            return $this->sessionParameters->get($name);
481
        }
482
    }
483
484
    /**
485
     * Returns TRUE if we've at least one session parameter configured, else FALSE.
486
     *
487
     * @return boolean TRUE if we've at least one session parameter configured, else FALSE
488
     */
489
    public function hasSessionParameters()
490
    {
491
        return sizeof($this->sessionParameters) > 0;
492
    }
493
494
    /**
495
     * Return's the servlet manager settings.
496
     *
497
     * @return \AppserverIo\Appserver\Application\Interfaces\ManagerSettingsInterface The servlet manager settings
498
     */
499
    public function getManagerSettings()
500
    {
501
        return $this->managerSettings;
502
    }
503
504
    /**
505
     * Tries to locate the resource related with the request.
506
     *
507
     * @param \AppserverIo\Psr\Servlet\Http\HttpServletRequestInterface $servletRequest The request instance to return the servlet for
508
     * @param array                                                     $args           The arguments passed to the servlet constructor
509
     *
510
     * @return \AppserverIo\Psr\Servlet\ServletInterface The requested servlet
511
     * @see \AppserverIo\Appserver\ServletEngine\ServletLocator::locate()
512
     */
513
    public function locate(HttpServletRequestInterface $servletRequest, array $args = array())
514
    {
515
516
        // load the servlet path => to locate the servlet
517
        $servletPath = $servletRequest->getServletPath();
518
519
        // if a session cookie has been sent, initialize the session manager and the session
520
        if ($manager = $this->getApplication()->search(SessionManagerInterface::IDENTIFIER)) {
521
            $requestedSessionName = $manager->getSessionSettings()->getSessionName();
522
            if ($servletRequest->hasCookie($requestedSessionName)) {
523
                $servletRequest->getCookie($requestedSessionName)->getValue();
524
            }
525
        }
526
527
        // return the instance
528
        return $this->lookup($servletPath, $args);
529
    }
530
531
    /**
532
     * Runs a lookup for the servlet with the passed class name and
533
     * session ID.
534
     *
535
     * @param string $servletPath The servlet path
536
     * @param array  $args        The arguments passed to the servlet constructor
537
     *
538
     * @return \AppserverIo\Psr\Servlet\ServletInterface The requested servlet
539
     */
540
    public function lookup($servletPath, array $args = array())
541
    {
542
        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

542
        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...
543
    }
544
545
    /**
546
     * Returns the identifier for the servlet manager instance.
547
     *
548
     * @return string
549
     * @see \AppserverIo\Psr\Application\ManagerInterface::getIdentifier()
550
     */
551
    public function getIdentifier()
552
    {
553
        return ServletContextInterface::IDENTIFIER;
554
    }
555
}
556