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

TimedObjectInvoker::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 3
cp 0
crap 6
rs 9.9
c 0
b 0
f 0
1
<?php
2
/**
3
 * \AppserverIo\Appserver\PersistenceContainer\TimedObjectInvoker
4
 *
5
 * NOTICE OF LICENSE
6
 *
7
 * This source file is subject to the Open Software License (OSL 3.0)
8
 * that is available through the world-wide-web at this URL:
9
 * http://opensource.org/licenses/osl-3.0.php
10
 *
11
 * PHP version 5
12
 *
13
 * @author    Tim Wagner <[email protected]>
14
 * @copyright 2015 TechDivision GmbH <[email protected]>
15
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
16
 * @link      https://github.com/appserver-io/appserver
17
 * @link      http://www.appserver.io
18
 */
19
20
namespace AppserverIo\Appserver\PersistenceContainer;
21
22
use Doctrine\Common\Annotations\AnnotationReader;
23
use AppserverIo\Psr\Servlet\SessionUtils;
24
use AppserverIo\Storage\StorageInterface;
25
use AppserverIo\Storage\GenericStackable;
26
use AppserverIo\Lang\Reflection\ClassInterface;
27
use AppserverIo\Lang\Reflection\MethodInterface;
28
use AppserverIo\Psr\Naming\InitialContext;
29
use AppserverIo\Psr\EnterpriseBeans\TimerInterface;
30
use AppserverIo\Psr\EnterpriseBeans\TimedObjectInterface;
31
use AppserverIo\Psr\EnterpriseBeans\TimedObjectInvokerInterface;
32
use AppserverIo\Psr\EnterpriseBeans\Annotations\Timeout;
33
use AppserverIo\Psr\EnterpriseBeans\Annotations\Schedule;
34
use AppserverIo\Psr\Application\ApplicationInterface;
35
use AppserverIo\Appserver\Core\Environment;
36
use AppserverIo\Appserver\Core\Utilities\EnvironmentKeys;
37
38
/**
39
 * Timed object invoker for an enterprise bean.
40
 *
41
 * @author    Tim Wagner <[email protected]>
42
 * @copyright 2015 TechDivision GmbH <[email protected]>
43
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
44
 * @link      https://github.com/appserver-io/appserver
45
 * @link      http://www.appserver.io
46
 *
47
 * @property \AppserverIo\Psr\Application\ApplicationInterface $application          The application instance
48
 * @property \AppserverIo\Lang\Reflection\ClassInterface       $timedObject          The timed object instance
49
 * @property \AppserverIo\Storage\StorageInterface             $timeoutMethods       The storage for the timeout methods
50
 * @property \AppserverIo\Lang\Reflection\MethodInterface      $defaultTimeoutMethod The timeout method instance
51
 */
52
class TimedObjectInvoker extends GenericStackable implements TimedObjectInvokerInterface
53
{
54
55
    /**
56
     * The execution environment.
57
     *
58
     * @var \AppserverIo\Appserver\Core\Environment
59
     */
60
    public static $environment;
61
62
    /**
63
     * The annotation reader instance singleton.
64
     *
65
     * @var \Doctrine\Common\Annotations\AnnotationReader
66
     */
67
    public static $annotationReaderInstance;
68
69
    /**
70
     * Return's the annotation reader instance.
71
     *
72
     * @return \Doctrine\Common\Annotations\AnnotationReader
73
     */
74
    public function getAnnotationReader()
75
    {
76
77
        // query whether or not an instance already exists
78
        if (TimedObjectInvoker::$annotationReaderInstance === null) {
79
            TimedObjectInvoker::$annotationReaderInstance = new AnnotationReader();
80
        }
81
82
        // return the instance
83
        return TimedObjectInvoker::$annotationReaderInstance;
84
    }
85
86
    /**
87
     * Return's the method annotation with the passed name, if available.
88
     *
89
     * @param \AppserverIo\Lang\Reflection\MethodInterface $reflectionMethod The reflection method to return the annotation for
90
     * @param string                                       $annotationName   The name of the annotation to return
91
     *
92
     * @return object|null The method annotation, or NULL if not available
93
     */
94
    public function getMethodAnnotation(MethodInterface $reflectionMethod, $annotationName)
95
    {
96
        return $this->getAnnotationReader()->getMethodAnnotation($reflectionMethod->toPhpReflectionMethod(), $annotationName);
97
    }
98
99
    /**
100
     * Injects the timed object instance.
101
     *
102
     * @param \AppserverIo\Lang\Reflection\ClassInterface $timedObject The timed object instance
103
     *
104
     * @return void
105
     */
106
    public function injectTimedObject(ClassInterface $timedObject)
107
    {
108
        $this->timedObject = $timedObject;
109
    }
110
111
    /**
112
     * Injects the storage for the timeout methods.
113
     *
114
     * @param \AppserverIo\Storage\StorageInterface $timeoutMethods The storage for the timeout methods
115
     *
116
     * @return void
117
     */
118
    public function injectTimeoutMethods(StorageInterface $timeoutMethods)
119
    {
120
        $this->timeoutMethods = $timeoutMethods;
121
    }
122
123
    /**
124
     * Injects the application instance.
125
     *
126
     * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application instance
127
     *
128
     * @return void
129
     */
130
    public function injectApplication(ApplicationInterface $application)
131
    {
132
        $this->application = $application;
133
    }
134
135
    /**
136
     * Return the timed object instance.
137
     *
138
     * @return \AppserverIo\Lang\Reflection\ClassInterface The timed object instance
139
     */
140
    public function getTimedObject()
141
    {
142
        return $this->timedObject;
143
    }
144
145
    /**
146
     * Returns the timeout methods.
147
     *
148
     * @return \AppserverIo\Storage\StorageInterface A collection of timeout methods
149
     **/
150
    public function getTimeoutMethods()
151
    {
152
        return $this->timeoutMethods;
153
    }
154
155
    /**
156
     * Returns the application instance.
157
     *
158
     * @return \AppserverIo\Psr\Application\ApplicationInterface The application instance
159
     */
160
    public function getApplication()
161
    {
162
        return $this->application;
163
    }
164
165
    /**
166
     * The globally unique identifier for this timed object invoker.
167
     *
168
     * @return string
169
     */
170
    public function getTimedObjectId()
171
    {
172
        return $this->getTimedObject()->getShortName();
173
    }
174
175
    /**
176
     * Responsible for invoking the timeout method on the target object.
177
     *
178
     * The timerservice implementation invokes this method as a callback when a timeout occurs for the
179
     * passed timer. The timerservice implementation will be responsible for passing the correct
180
     * timeout method corresponding to the <code>timer</code> on which the timeout has occurred.
181
     *
182
     * @param \AppserverIo\Psr\EnterpriseBeans\TimerInterface $timer         The timer that is passed to timeout
183
     * @param \AppserverIo\Lang\Reflection\MethodInterface    $timeoutMethod The timeout method
184
     *
185
     * @return void
186
     */
187
    public function callTimeout(TimerInterface $timer, MethodInterface $timeoutMethod = null)
188
    {
189
190
        try {
191
            // synchronize the application instance and register the class loaders
192
            $application = $this->getApplication();
193
            $application->registerClassLoaders();
194
195
            // register the applications annotation registries
196
            $application->registerAnnotationRegistries();
197
198
            // initialize the initial context instance
199
            $initialContext = new InitialContext();
200
            $initialContext->injectApplication($application);
201
202
            // add the application instance to the environment
203
            Environment::singleton()->setAttribute(EnvironmentKeys::APPLICATION, $application);
204
205
            // create s simulated request/session ID whereas session equals request ID
206
            Environment::singleton()->setAttribute(EnvironmentKeys::SESSION_ID, $sessionId = SessionUtils::generateRandomString());
207
            Environment::singleton()->setAttribute(EnvironmentKeys::REQUEST_ID, $sessionId);
208
209
            // log a message with the timed object information
210
            \info(sprintf('Now invoke timed object "%s" with session ID "%s"', $this->getTimedObjectId(), $sessionId));
211
212
            // lookup the enterprise bean using the initial context
213
            $instance = $initialContext->lookup($this->getTimedObjectId());
214
215
            // check if the timeout method has been passed
216
            if ($timeoutMethod != null) {
217
                // if yes, invoke it on the proxy
218
                $callback = array($instance, $timeoutMethod->getMethodName());
219
                call_user_func_array($callback, array($timer));
220
                return;
221
            }
222
223
            // check if we've a default timeout method
224
            if ($this->defaultTimeoutMethod != null) {
225
                // if yes, invoke it on the proxy
226
                $callback = array($instance, $this->defaultTimeoutMethod->getMethodName());
227
                call_user_func_array($callback, array($timer));
228
                return;
229
            }
230
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
231
        } catch (\Exception $e) {
232
            error_log($e->__toString());
233
        }
234
    }
235
236
    /**
237
     * Initializes the timed object invoker with the methods annotated
238
     * with the @Timeout or @Schedule annotation.
239
     *
240
     * @return void
241
     */
242
    public function start()
243
    {
244
245
        // create a reflection object instance of the timed object
246
        $reflectionClass = $this->getTimedObject();
247
248
        // first check if the bean implements the timed object interface => so we've a default timeout method
249
        if ($reflectionClass->implementsInterface('AppserverIo\Psr\EnterpriseBeans\TimedObjectInterface')) {
250
            $this->defaultTimeoutMethod = $reflectionClass->getMethod(TimedObjectInterface::DEFAULT_TIMEOUT_METHOD);
251
        }
252
253
        // check the methods of the bean for a @Timeout annotation => overwrite the default
254
        // timeout method defined by the interface
255
        /** @var \AppserverIo\Lang\Reflection\MethodInterface $timeoutMethod */
256
        foreach ($reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $timeoutMethod) {
257
            // check if the timed object instance has @Timeout annotation => default timeout method
258
            if ($this->getMethodAnnotation($timeoutMethod, Timeout::class)) {
259
                $this->defaultTimeoutMethod = $timeoutMethod;
260
            }
261
262
            // check if the timed object instance has @Schedule annotation
263
            if ($this->getMethodAnnotation($timeoutMethod, Schedule::class)) {
264
                $this->timeoutMethods[$timeoutMethod->getMethodName()] = $timeoutMethod;
265
            }
266
        }
267
    }
268
}
269