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