Completed
Push — master ( 9dc9e2...92022a )
by Tim
12s
created

TimerServiceRegistry::getAnnotationReader()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 11
ccs 0
cts 1
cp 0
crap 6
rs 9.9
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * \AppserverIo\Appserver\PersistenceContainer\TimerServiceRegistry
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\PersistenceContainer;
22
23
use Doctrine\Common\Annotations\AnnotationReader;
24
use AppserverIo\Storage\StackableStorage;
25
use AppserverIo\Lang\Reflection\ClassInterface;
26
use AppserverIo\Psr\Application\ApplicationInterface;
27
use AppserverIo\Psr\EnterpriseBeans\Annotations\Stateless;
28
use AppserverIo\Psr\EnterpriseBeans\Annotations\Singleton;
29
use AppserverIo\Psr\EnterpriseBeans\Annotations\MessageDriven;
30
use AppserverIo\Psr\EnterpriseBeans\ServiceProviderInterface;
31
use AppserverIo\Psr\EnterpriseBeans\ServiceExecutorInterface;
32
use AppserverIo\Psr\EnterpriseBeans\TimerServiceContextInterface;
33
use AppserverIo\Psr\EnterpriseBeans\ServiceAlreadyRegisteredException;
34
35
/**
36
 * The timer service registry handles an application's timer services.
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\Psr\EnterpriseBeans\ServiceExecutorInterface                 $timerServiceExecutor     The timer service executor
45
 * @property  \AppserverIo\Appserver\PersistenceContainer\TimerFactoryInterface         $timerFactory             The timer factory
46
 * @property  \AppserverIo\Appserver\PersistenceContainer\CalendarTimerFactoryInterface $calendarTimerFactory     The calendar timer factory
47
 */
48
class TimerServiceRegistry extends ServiceRegistry implements TimerServiceContextInterface
49
{
50
51
    /**
52
     * The annotation reader instance singleton.
53
     *
54
     * @var \Doctrine\Common\Annotations\AnnotationReader
55
     */
56
    public static $annotationReaderInstance;
57
58
    /**
59
     * Return's the annotation reader instance.
60
     *
61
     * @return \Doctrine\Common\Annotations\AnnotationReader
62
     */
63
    public function getAnnotationReader()
64
    {
65
66
        // query whether or not an instance already exists
67
        if (TimerServiceRegistry::$annotationReaderInstance === null) {
68
            TimerServiceRegistry::$annotationReaderInstance = new AnnotationReader();
69
        }
70
71
        // return the instance
72
        return TimerServiceRegistry::$annotationReaderInstance;
73
    }
74
75
    /**
76
     * Return's the class annotation with the passed name, if available.
77
     *
78
     * @param \AppserverIo\Lang\Reflection\ClassInterface $reflectionClass The reflection class to return the annotation for
79
     * @param string                                      $annotationName  The name of the annotation to return
80
     *
81
     * @return object|null The class annotation, or NULL if not available
82
     */
83
    public function getClassAnnotation(ClassInterface $reflectionClass, $annotationName)
84
    {
85
        return $this->getAnnotationReader()->getClassAnnotation($reflectionClass->toPhpReflectionClass(), $annotationName);
86
    }
87
88
    /**
89
     * Injects the service executor for the timer service registry.
90
     *
91
     * @param \AppserverIo\Psr\EnterpriseBeans\ServiceExecutorInterface $timerServiceExecutor The service executor
92
     *
93
     * @return void
94
     */
95
    public function injectTimerServiceExecutor(ServiceExecutorInterface $timerServiceExecutor)
96
    {
97
        $this->timerServiceExecutor = $timerServiceExecutor;
98
    }
99
100
    /**
101
     * Injects the timer factory for the timer service registry.
102
     *
103
     * @param \AppserverIo\Appserver\PersistenceContainer\TimerFactoryInterface $timerFactory The timer factory
104
     *
105
     * @return void
106
     */
107
    public function injectTimerFactory(TimerFactoryInterface $timerFactory)
108
    {
109
        $this->timerFactory = $timerFactory;
110
    }
111
112
    /**
113
     * Injects the calendar timer factory for the timer service registry.
114
     *
115
     * @param \AppserverIo\Appserver\PersistenceContainer\CalendarTimerFactoryInterface $calendarTimerFactory The calendar timer factory
116
     *
117
     * @return void
118
     */
119
    public function injectCalendarTimerFactory(CalendarTimerFactoryInterface $calendarTimerFactory)
120
    {
121
        $this->calendarTimerFactory = $calendarTimerFactory;
122
    }
123
124
    /**
125
     * Returns the service executor for the timer service registry.
126
     *
127
     * @return \AppserverIo\Psr\EnterpriseBeans\ServiceExecutorInterface The timer service executor instance
128
     */
129
    public function getTimerServiceExecutor()
130
    {
131
        return $this->timerServiceExecutor;
132
    }
133
134
    /**
135
     * Returns the timer factory for the timer service registry.
136
     *
137
     * @return \AppserverIo\Appserver\PersistenceContainer\TimerFactoryInterface The timer factory instance
138
     */
139
    public function getTimerFactory()
140
    {
141
        return $this->timerFactory;
142
    }
143
144
    /**
145
     * Returns the calendar timer factory for the timer service registry.
146
     *
147
     * @return \AppserverIo\Appserver\PersistenceContainer\CalendarTimerFactoryInterface The calendar timer factory instance
148
     */
149
    public function getCalendarTimerFactory()
150
    {
151
        return $this->calendarTimerFactory;
152
    }
153
154
    /**
155
     * Has been automatically invoked by the container after the application
156
     * instance has been created.
157
     *
158
     * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application instance
159
     *
160
     * @return void
161
     * @see \AppserverIo\Psr\Application\ManagerInterface::initialize()
162
     */
163
    public function initialize(ApplicationInterface $application)
164
    {
165
166
        // build up META-INF directory var
167
        $metaInfDir = $application->getWebappPath() . DIRECTORY_SEPARATOR .'META-INF';
168
169
        // check if we've found a valid directory
170
        if (is_dir($metaInfDir) === false) {
171
            return;
172
        }
173
174
        // load the timer service executor and timer factories
175
        $timerFactory = $this->getTimerFactory();
176
        $calendarTimerFactory = $this->getCalendarTimerFactory();
177
        $timerServiceExecutor = $this->getTimerServiceExecutor();
178
179
        // load the service to iterate over application folders
180
        /** @var \AppserverIo\Appserver\Core\Api\DeploymentService $service */
181
        $service = $application->newService('AppserverIo\Appserver\Core\Api\DeploymentService');
182
        $phpFiles = $service->globDir($metaInfDir . DIRECTORY_SEPARATOR . '*.php');
183
184
        // iterate all php files
185
        foreach ($phpFiles as $phpFile) {
186
            try {
187
                // cut off the META-INF directory and replace OS specific directory separators
188
                $relativePathToPhpFile = str_replace(DIRECTORY_SEPARATOR, '\\', str_replace($metaInfDir, '', $phpFile));
189
190
                // now cut off the first directory, that will be '/classes' by default
191
                $pregResult = preg_replace('%^(\\\\*)[^\\\\]+%', '', $relativePathToPhpFile);
192
                $className = substr($pregResult, 0, -4);
193
194
                // create the reflection class instance
195
                $reflectionClass = new \ReflectionClass($className);
196
197
                // initialize the timed object instance with the data from the reflection class
198
                $timedObject = TimedObject::fromPhpReflectionClass($reflectionClass);
199
200
                // check if we have a bean with a @Stateless, @Singleton or @MessageDriven annotation
201
                if ($this->getClassAnnotation($timedObject, Stateless::class) ||
202
                    $this->getClassAnnotation($timedObject, Singleton::class) ||
203
                    $this->getClassAnnotation($timedObject, MessageDriven::class)
204
                ) {
205
                    // initialize the stackable for the timeout methods
206
                    $timeoutMethods = new StackableStorage();
207
208
                    // create the timed object invoker
209
                    $timedObjectInvoker = new TimedObjectInvoker();
210
                    $timedObjectInvoker->injectApplication($application);
211
                    $timedObjectInvoker->injectTimedObject($timedObject);
212
                    $timedObjectInvoker->injectTimeoutMethods($timeoutMethods);
213
                    $timedObjectInvoker->start(PTHREADS_INHERIT_NONE|PTHREADS_INHERIT_CONSTANTS);
0 ignored issues
show
Unused Code introduced by
The call to TimedObjectInvoker::start() has too many arguments starting with PTHREADS_INHERIT_NONE | PTHREADS_INHERIT_CONSTANTS.

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.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
214
215
                    // initialize the stackable for the timers
216
                    $timers = new StackableStorage();
217
218
                    // initialize the timer service
219
                    $timerService = new TimerService();
220
                    $timerService->injectTimers($timers);
221
                    $timerService->injectTimerFactory($timerFactory);
222
                    $timerService->injectTimedObjectInvoker($timedObjectInvoker);
223
                    $timerService->injectCalendarTimerFactory($calendarTimerFactory);
224
                    $timerService->injectTimerServiceExecutor($timerServiceExecutor);
225
                    $timerService->start(PTHREADS_INHERIT_NONE|PTHREADS_INHERIT_CONSTANTS);
0 ignored issues
show
Unused Code introduced by
The call to TimerService::start() has too many arguments starting with PTHREADS_INHERIT_NONE | PTHREADS_INHERIT_CONSTANTS.

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.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
226
227
                    // register the initialized timer service
228
                    $this->register($timerService);
229
230
                    // log a message that the timer service has been registered
231
                    $application->getInitialContext()->getSystemLogger()->debug(
232
                        sprintf(
233
                            'Successfully registered timer service for bean %s',
234
                            $reflectionClass->getName()
0 ignored issues
show
Bug introduced by
Consider using $reflectionClass->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
235
                        )
236
                    );
237
                }
238
239
            // if class can not be reflected continue with next class
240
            } catch (\Exception $e) {
241
                // log an error message
242
                $application->getInitialContext()->getSystemLogger()->error($e->__toString());
243
244
                // proceed with the next bean
245
                continue;
246
            }
247
        }
248
    }
249
250
    /**
251
     * Attaches the passed service, to the context.
252
     *
253
     * @param \AppserverIo\Psr\EnterpriseBeans\ServiceProviderInterface $instance The service instance to attach
254
     *
255
     * @return void
256
     * @throws \AppserverIo\Psr\EnterpriseBeans\ServiceAlreadyRegisteredException Is thrown if the passed service has already been registered
257
     */
258
    public function register(ServiceProviderInterface $instance)
259
    {
260
261
        // check if the service has already been registered
262
        if ($this->getServices()->has($pk = $instance->getPrimaryKey())) {
263
            throw new ServiceAlreadyRegisteredException(
264
                sprintf(
265
                    'It is not allowed to register service %s with primary key %s more than on times',
266
                    $instance->getServiceName(),
267
                    $pk
268
                )
269
            );
270
        }
271
272
        // register the service using the primary key
273
        $this->getServices()->set($pk, $instance);
274
    }
275
276
    /**
277
     * Initializes the manager instance.
278
     *
279
     * @return string
280
     * @see \AppserverIo\Psr\Application\ManagerInterface::initialize()
281
     */
282
    public function getIdentifier()
283
    {
284
        return TimerServiceContextInterface::IDENTIFIER;
285
    }
286
287
    /**
288
     * Shutdown the session manager instance.
289
     *
290
     * @return void
291
     * \AppserverIo\Psr\Application\ManagerInterface::stop()
292
     */
293
    public function stop()
294
    {
295
        $this->getTimerServiceExecutor()->stop();
296
        $this->getCalendarTimerFactory()->stop();
297
        $this->getTimerFactory()->stop();
298
    }
299
}
300