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 }