1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.scxml2;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.LinkedList;
23 import java.util.Map;
24 import java.util.Queue;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.commons.scxml2.env.SimpleDispatcher;
29 import org.apache.commons.scxml2.env.SimpleErrorReporter;
30 import org.apache.commons.scxml2.invoke.Invoker;
31 import org.apache.commons.scxml2.invoke.InvokerException;
32 import org.apache.commons.scxml2.invoke.SimpleSCXMLInvoker;
33 import org.apache.commons.scxml2.model.Invoke;
34 import org.apache.commons.scxml2.model.ModelException;
35 import org.apache.commons.scxml2.model.SCXML;
36
37
38
39
40
41 public class SCXMLExecutionContext implements SCXMLIOProcessor {
42
43
44
45
46 public static final String SCXML_INVOKER_TYPE_URI = "http://www.w3.org/TR/scxml/";
47
48
49
50 public static final String SCXML_INVOKER_TYPE = "scxml";
51
52
53
54
55 private Log appLog = LogFactory.getLog(SCXMLExecutionContext.class);
56
57
58
59
60 private final ActionExecutionContext actionExecutionContext;
61
62
63
64
65 private final SCXMLExecutor scxmlExecutor;
66
67
68
69
70 private SCInstance scInstance;
71
72
73
74
75 private Evaluator evaluator;
76
77
78
79
80 private SCXMLIOProcessor externalIOProcessor;
81
82
83
84
85 private EventDispatcher eventdispatcher;
86
87
88
89
90 private ErrorReporter errorReporter = null;
91
92
93
94
95 private NotificationRegistry notificationRegistry;
96
97
98
99
100 private final Queue<TriggerEvent> internalEventQueue = new LinkedList<TriggerEvent>();
101
102
103
104
105 private final Map<String, Class<? extends Invoker>> invokerClasses = new HashMap<String, Class<? extends Invoker>>();
106
107
108
109
110 private final Map<Invoke, String> invokeIds = new HashMap<Invoke, String>();
111
112
113
114
115 private final Map<String, Invoker> invokers = new HashMap<String, Invoker>();
116
117
118
119
120 private final Map<String, SCXMLIOProcessor> ioProcessors = new HashMap<String, SCXMLIOProcessor>();
121
122
123
124
125 private boolean checkLegalConfiguration = true;
126
127
128
129
130 private String sessionId;
131
132
133
134
135
136
137
138
139
140 protected SCXMLExecutionContext(SCXMLExecutor scxmlExecutor, Evaluator evaluator,
141 EventDispatcher eventDispatcher, ErrorReporter errorReporter) {
142 this.scxmlExecutor = scxmlExecutor;
143 this.externalIOProcessor = scxmlExecutor;
144 this.evaluator = evaluator;
145 this.eventdispatcher = eventDispatcher != null ? eventDispatcher : new SimpleDispatcher();
146 this.errorReporter = errorReporter != null ? errorReporter : new SimpleErrorReporter();
147 this.notificationRegistry = new NotificationRegistry();
148
149 this.scInstance = new SCInstance(this, this.evaluator, this.errorReporter);
150 this.actionExecutionContext = new ActionExecutionContext(this);
151
152 ioProcessors.put(SCXMLIOProcessor.DEFAULT_EVENT_PROCESSOR, getExternalIOProcessor());
153 ioProcessors.put(SCXMLIOProcessor.SCXML_EVENT_PROCESSOR, getExternalIOProcessor());
154 ioProcessors.put(SCXMLIOProcessor.INTERNAL_EVENT_PROCESSOR, getInternalIOProcessor());
155 if (scxmlExecutor.getParentSCXMLExecutor() != null) {
156 ioProcessors.put(SCXMLIOProcessor.PARENT_EVENT_PROCESSOR, scxmlExecutor.getParentSCXMLExecutor());
157 }
158 initializeIOProcessors();
159 registerInvokerClass(SCXML_INVOKER_TYPE_URI, SimpleSCXMLInvoker.class);
160 registerInvokerClass(SCXML_INVOKER_TYPE, SimpleSCXMLInvoker.class);
161 }
162
163 public SCXMLExecutor getSCXMLExecutor() {
164 return scxmlExecutor;
165 }
166
167 public SCXMLIOProcessor getExternalIOProcessor() {
168 return externalIOProcessor;
169 }
170
171 public SCXMLIOProcessor getInternalIOProcessor() {
172 return this;
173 }
174
175
176
177
178 public ActionExecutionContext getActionExecutionContext() {
179 return actionExecutionContext;
180 }
181
182
183
184
185 public boolean isRunning() {
186 return scInstance.isRunning();
187 }
188
189
190
191
192 public void stopRunning() {
193 scInstance.setRunning(false);
194 }
195
196
197
198
199
200 public void setCheckLegalConfiguration(boolean checkLegalConfiguration) {
201 this.checkLegalConfiguration = checkLegalConfiguration;
202 }
203
204
205
206
207 public boolean isCheckLegalConfiguration() {
208 return checkLegalConfiguration;
209 }
210
211
212
213
214
215
216
217 public void initialize() throws ModelException {
218 if (!invokeIds.isEmpty()) {
219 for (Invoke invoke : new ArrayList<Invoke>(invokeIds.keySet())) {
220 cancelInvoker(invoke);
221 }
222 }
223 internalEventQueue.clear();
224 scInstance.initialize();
225 initializeIOProcessors();
226 scInstance.setRunning(true);
227 }
228
229
230
231
232 public Log getAppLog() {
233 return appLog;
234 }
235
236
237
238
239 public SCXML getStateMachine() {
240 return scInstance.getStateMachine();
241 }
242
243
244
245
246
247
248
249
250
251
252 protected void setStateMachine(SCXML stateMachine) throws ModelException {
253 scInstance.setStateMachine(stateMachine);
254
255 this.evaluator = scInstance.getEvaluator();
256 initializeIOProcessors();
257 }
258
259
260
261
262
263
264 public String getLocation() {
265 return null;
266 }
267
268
269
270
271 public SCInstance getScInstance() {
272 return scInstance;
273 }
274
275
276
277
278 public Evaluator getEvaluator() {
279 return evaluator;
280 }
281
282
283
284
285
286
287
288
289
290
291 protected void setEvaluator(Evaluator evaluator) throws ModelException {
292 scInstance.setEvaluator(evaluator, false);
293
294 this.evaluator = scInstance.getEvaluator();
295 initializeIOProcessors();
296 }
297
298
299
300
301 public ErrorReporter getErrorReporter() {
302 return errorReporter;
303 }
304
305
306
307
308
309
310 protected void setErrorReporter(ErrorReporter errorReporter) {
311 this.errorReporter = errorReporter != null ? errorReporter : new SimpleErrorReporter();
312 try {
313 scInstance.setErrorReporter(errorReporter);
314 }
315 catch (ModelException me) {
316
317 }
318 }
319
320
321
322
323 public EventDispatcher getEventDispatcher() {
324 return eventdispatcher;
325 }
326
327
328
329
330
331
332 protected void setEventdispatcher(EventDispatcher eventdispatcher) {
333 this.eventdispatcher = eventdispatcher != null ? eventdispatcher : new SimpleDispatcher();
334 }
335
336
337
338
339 public NotificationRegistry getNotificationRegistry() {
340 return notificationRegistry;
341 }
342
343
344
345
346 protected void initializeIOProcessors() {
347 if (scInstance.getEvaluator() != null) {
348
349 String currentSessionId = (String)getScInstance().getSystemContext().get(SCXMLSystemContext.SESSIONID_KEY);
350 if (sessionId != null && !sessionId.equals(currentSessionId)) {
351
352 ioProcessors.remove(SCXMLIOProcessor.SCXML_SESSION_EVENT_PROCESSOR_PREFIX+sessionId);
353 }
354 sessionId = currentSessionId;
355 if (!ioProcessors.containsKey(SCXMLIOProcessor.SCXML_SESSION_EVENT_PROCESSOR_PREFIX+sessionId)) {
356 ioProcessors.put(SCXMLIOProcessor.SCXML_SESSION_EVENT_PROCESSOR_PREFIX+sessionId, getExternalIOProcessor());
357 }
358 getScInstance().getSystemContext().setLocal(SCXMLSystemContext.IOPROCESSORS_KEY, Collections.unmodifiableMap(ioProcessors));
359 }
360 }
361
362
363
364
365
366
367
368
369 protected SCInstance detachInstance() {
370 SCInstance instance = scInstance;
371 scInstance.detach();
372 Map<String, Object> systemVars = scInstance.getSystemContext().getVars();
373 systemVars.remove(SCXMLSystemContext.IOPROCESSORS_KEY);
374 systemVars.remove(SCXMLSystemContext.EVENT_KEY);
375 scInstance = null;
376 return instance;
377 }
378
379
380
381
382
383
384
385
386 protected void attachInstance(SCInstance instance) {
387 if (scInstance != null ) {
388 scInstance.detach();
389 }
390 scInstance = instance;
391 if (scInstance != null) {
392 scInstance.detach();
393 try {
394 scInstance.setInternalIOProcessor(this);
395 scInstance.setEvaluator(evaluator, true);
396 scInstance.setErrorReporter(errorReporter);
397 initializeIOProcessors();
398 }
399 catch (ModelException me) {
400
401 }
402 }
403 }
404
405
406
407
408
409
410
411 protected void registerInvokerClass(final String type, final Class<? extends Invoker> invokerClass) {
412 invokerClasses.put(type, invokerClass);
413 }
414
415
416
417
418
419
420 protected void unregisterInvokerClass(final String type) {
421 invokerClasses.remove(type);
422 }
423
424
425
426
427
428
429
430
431
432
433 public Invoker newInvoker(final String type) throws InvokerException {
434 Class<? extends Invoker> invokerClass = invokerClasses.get(type);
435 if (invokerClass == null) {
436 throw new InvokerException("No Invoker registered for type \"" + type + "\"");
437 }
438 try {
439 return invokerClass.newInstance();
440 } catch (InstantiationException ie) {
441 throw new InvokerException(ie.getMessage(), ie.getCause());
442 } catch (IllegalAccessException iae) {
443 throw new InvokerException(iae.getMessage(), iae.getCause());
444 }
445 }
446
447
448
449
450
451
452
453
454
455
456 public Invoker getInvoker(final Invoke invoke) {
457 return invokers.get(invokeIds.get(invoke));
458 }
459
460
461
462
463
464
465
466
467 public void registerInvoker(final Invoke invoke, final Invoker invoker) throws InvokerException {
468 String invokeId = invoker.getInvokeId();
469 if (invokeId == null) {
470 throw new InvokerException("Registering an Invoker without invokerId");
471 }
472 invokeIds.put(invoke, invokeId);
473 invokers.put(invokeId, invoker);
474 ioProcessors.put(SCXMLIOProcessor.EVENT_PROCESSOR_ALIAS_PREFIX+invoke.getId(), invoker.getChildIOProcessor());
475 initializeIOProcessors();
476 }
477
478
479
480
481
482 public void removeInvoker(final Invoke invoke) {
483 invokers.remove(invokeIds.remove(invoke));
484 ioProcessors.remove(SCXMLIOProcessor.EVENT_PROCESSOR_ALIAS_PREFIX+invoke.getId());
485 initializeIOProcessors();
486 }
487
488
489
490
491 public Map<Invoke, String> getInvokeIds() {
492 return invokeIds;
493 }
494
495
496
497
498
499
500
501 public void cancelInvoker(Invoke invoke) {
502 String invokeId = invokeIds.get(invoke);
503 if (invokeId != null) {
504 try {
505 invokers.get(invokeId).cancel();
506 } catch (InvokerException ie) {
507 TriggerEvent te = new TriggerEvent("failed.invoke.cancel."+invokeId, TriggerEvent.ERROR_EVENT);
508 addEvent(te);
509 }
510 removeInvoker(invoke);
511 }
512 }
513
514
515
516
517
518 @Override
519 public void addEvent(TriggerEvent event) {
520 internalEventQueue.add(event);
521 }
522
523
524
525
526 public TriggerEvent nextInternalEvent() {
527 return internalEventQueue.poll();
528 }
529
530
531
532
533 public boolean hasPendingInternalEvent() {
534 return !internalEventQueue.isEmpty();
535 }
536 }