1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.scxml2.env;
18
19 import java.io.Serializable;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.Map;
23 import java.util.Timer;
24 import java.util.TimerTask;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.commons.scxml2.EventDispatcher;
29 import org.apache.commons.scxml2.SCXMLIOProcessor;
30 import org.apache.commons.scxml2.TriggerEvent;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 public class SimpleDispatcher implements EventDispatcher, Serializable {
46
47
48 private static final long serialVersionUID = 1L;
49
50
51
52
53 class DelayedEventTask extends TimerTask {
54
55
56
57
58 private String id;
59
60
61
62
63 private String event;
64
65
66
67
68 private Object payload;
69
70
71
72
73 private SCXMLIOProcessor target;
74
75
76
77
78
79
80
81
82
83 DelayedEventTask(final String id, final String event, final Object payload, SCXMLIOProcessor target) {
84 super();
85 this.id = id;
86 this.event = event;
87 this.payload = payload;
88 this.target = target;
89 }
90
91
92
93
94 @Override
95 public void run() {
96 timers.remove(id);
97 target.addEvent(new TriggerEvent(event, TriggerEvent.SIGNAL_EVENT, payload));
98 if (log.isDebugEnabled()) {
99 log.debug("Fired event '" + event + "' as scheduled by "
100 + "<send> with id '" + id + "'");
101 }
102 }
103 }
104
105
106 private Log log = LogFactory.getLog(EventDispatcher.class);
107
108
109
110
111
112 private Map<String, Timer> timers = Collections.synchronizedMap(new HashMap<String, Timer>());
113
114
115
116
117
118
119 protected Log getLog() {
120 return log;
121 }
122
123
124
125
126
127
128 protected void setLog(Log log) {
129 this.log = log;
130 }
131
132
133
134
135
136
137 protected Map<String, Timer> getTimers() {
138 return timers;
139 }
140
141
142
143
144 public void cancel(final String sendId) {
145 if (log.isInfoEnabled()) {
146 log.info("cancel( sendId: " + sendId + ")");
147 }
148 if (!timers.containsKey(sendId)) {
149 return;
150 }
151 Timer timer = timers.get(sendId);
152 if (timer != null) {
153 timer.cancel();
154 if (log.isDebugEnabled()) {
155 log.debug("Cancelled event scheduled by <send> with id '"
156 + sendId + "'");
157 }
158 }
159 timers.remove(sendId);
160 }
161
162
163
164
165 public void send(final Map<String, SCXMLIOProcessor> ioProcessors, final String id, final String target,
166 final String type, final String event, final Object data, final Object hints, final long delay) {
167 if (log.isInfoEnabled()) {
168 StringBuilder buf = new StringBuilder();
169 buf.append("send ( id: ").append(id);
170 buf.append(", target: ").append(target);
171 buf.append(", type: ").append(type);
172 buf.append(", event: ").append(event);
173 buf.append(", data: ").append(String.valueOf(data));
174 buf.append(", hints: ").append(String.valueOf(hints));
175 buf.append(", delay: ").append(delay);
176 buf.append(')');
177 log.info(buf.toString());
178 }
179
180
181
182 if (type == null || type.equalsIgnoreCase(SCXMLIOProcessor.SCXML_EVENT_PROCESSOR) ||
183 type.equals(SCXMLIOProcessor.DEFAULT_EVENT_PROCESSOR)) {
184
185 SCXMLIOProcessor ioProcessor;
186
187 boolean internal = false;
188
189 if (target == null) {
190 ioProcessor = ioProcessors.get(SCXMLIOProcessor.SCXML_EVENT_PROCESSOR);
191 }
192 else if (ioProcessors.containsKey(target)) {
193 ioProcessor = ioProcessors.get(target);
194 internal = SCXMLIOProcessor.INTERNAL_EVENT_PROCESSOR.equals(target);
195 }
196 else if (SCXMLIOProcessor.INTERNAL_EVENT_PROCESSOR.equals(target)) {
197 ioProcessor = ioProcessors.get(SCXMLIOProcessor.INTERNAL_EVENT_PROCESSOR);
198 internal = true;
199 }
200 else {
201
202 if (log.isWarnEnabled()) {
203 log.warn("<send>: Unavailable target - " + target);
204 }
205 ioProcessors.get(SCXMLIOProcessor.INTERNAL_EVENT_PROCESSOR).
206 addEvent(new TriggerEvent(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT));
207 return;
208 }
209
210 if (event == null) {
211 if (log.isWarnEnabled()) {
212 log.warn("<send>: Cannot send without event name");
213 }
214 ioProcessors.get(SCXMLIOProcessor.INTERNAL_EVENT_PROCESSOR).
215 addEvent(new TriggerEvent(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT));
216 }
217
218 else if (!internal && delay > 0L) {
219
220 Timer timer = new Timer(true);
221 timer.schedule(new DelayedEventTask(id, event, data, ioProcessor), delay);
222 timers.put(id, timer);
223 if (log.isDebugEnabled()) {
224 log.debug("Scheduled event '" + event + "' with delay "
225 + delay + "ms, as specified by <send> with id '"
226 + id + "'");
227 }
228 }
229 else {
230 ioProcessor.addEvent(new TriggerEvent(event, TriggerEvent.SIGNAL_EVENT, data));
231 }
232 }
233 else {
234 if (log.isWarnEnabled()) {
235 log.warn("<send>: Unsupported type - " + type);
236 }
237 ioProcessors.get(SCXMLIOProcessor.INTERNAL_EVENT_PROCESSOR).
238 addEvent(new TriggerEvent(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT));
239 }
240 }
241 }
242