1
2
3
4
5
6
7
8
9
10
11 package org.mule.module.bpm;
12
13 import org.mule.DefaultMuleEvent;
14 import org.mule.DefaultMuleMessage;
15 import org.mule.MessageExchangePattern;
16 import org.mule.RequestContext;
17 import org.mule.api.MuleEvent;
18 import org.mule.api.MuleException;
19 import org.mule.api.MuleMessage;
20 import org.mule.api.config.MuleProperties;
21 import org.mule.api.construct.FlowConstruct;
22 import org.mule.api.endpoint.EndpointBuilder;
23 import org.mule.api.endpoint.OutboundEndpoint;
24 import org.mule.api.lifecycle.Disposable;
25 import org.mule.api.lifecycle.Initialisable;
26 import org.mule.api.lifecycle.InitialisationException;
27 import org.mule.api.transport.DispatchException;
28 import org.mule.api.transport.PropertyScope;
29 import org.mule.config.i18n.MessageFactory;
30 import org.mule.session.DefaultMuleSession;
31 import org.mule.transport.NullPayload;
32 import org.mule.util.StringUtils;
33
34 import java.util.HashMap;
35 import java.util.Map;
36
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39
40
41
42
43 public class Process implements Initialisable, Disposable, MessageService
44 {
45
46 private final BPMS bpms;
47
48
49 private final String name;
50
51
52 private final String resource;
53
54
55 protected final String processIdField;
56
57
58 private FlowConstruct flowConstruct;
59
60 public static final String BPM_PROPERTY_PREFIX = "BPM_";
61
62 public static final String PROPERTY_ENDPOINT =
63 MuleProperties.PROPERTY_PREFIX + BPM_PROPERTY_PREFIX + "ENDPOINT";
64 public static final String PROPERTY_PROCESS_TYPE =
65 MuleProperties.PROPERTY_PREFIX + BPM_PROPERTY_PREFIX + "PROCESS_TYPE";
66 public static final String PROPERTY_PROCESS_ID =
67 MuleProperties.PROPERTY_PREFIX + BPM_PROPERTY_PREFIX + "PROCESS_ID";
68 public static final String PROPERTY_ACTION =
69 MuleProperties.PROPERTY_PREFIX + BPM_PROPERTY_PREFIX + "ACTION";
70 public static final String PROPERTY_TRANSITION =
71 MuleProperties.PROPERTY_PREFIX + BPM_PROPERTY_PREFIX + "TRANSITION";
72 public static final String PROPERTY_PROCESS_STARTED =
73 MuleProperties.PROPERTY_PREFIX + BPM_PROPERTY_PREFIX + "STARTED";
74
75 public static final String ACTION_START = "start";
76 public static final String ACTION_ADVANCE = "advance";
77 public static final String ACTION_UPDATE = "update";
78 public static final String ACTION_ABORT = "abort";
79
80 public static final String PROCESS_VARIABLE_INCOMING = "incoming";
81 public static final String PROCESS_VARIABLE_INCOMING_SOURCE = "incomingSource";
82 public static final String PROCESS_VARIABLE_DATA = "data";
83
84 protected transient Log logger = LogFactory.getLog(getClass());
85
86 public Process(BPMS bpms, String name, String resource, FlowConstruct flowConstruct)
87 {
88 this(bpms, name, resource, null, flowConstruct);
89 }
90
91 public Process(BPMS bpms, String name, String resource, String processIdField, FlowConstruct flowConstruct)
92 {
93 this.bpms = bpms;
94 this.name = name;
95 this.resource = resource;
96 this.processIdField = processIdField;
97 this.flowConstruct = flowConstruct;
98 }
99
100 public void initialise() throws InitialisationException
101 {
102 try
103 {
104 bpms.deployProcess(resource);
105 }
106 catch (Exception e)
107 {
108 throw new InitialisationException(e, this);
109 }
110 }
111
112 public void dispose()
113 {
114 try
115 {
116 bpms.undeployProcess(resource);
117 }
118 catch (Exception e)
119 {
120 logger.warn(e.getMessage());
121 }
122 }
123
124 protected Object processAction(MuleEvent event) throws Exception
125 {
126
127 Object process;
128
129
130 Map processVariables = new HashMap();
131 if (event != null)
132 {
133 populateProcessVariables(event, processVariables, PropertyScope.INVOCATION);
134 populateProcessVariables(event, processVariables, PropertyScope.INBOUND);
135
136 Object payload = event.getMessage().getPayload();
137 if (payload != null && !(payload instanceof NullPayload))
138 {
139
140 processVariables.put(PROCESS_VARIABLE_INCOMING, payload);
141
142
143 String originatingEndpoint = event.getMessage().getInboundProperty(MuleProperties.MULE_ORIGINATING_ENDPOINT_PROPERTY);
144 if (StringUtils.isNotEmpty(originatingEndpoint))
145 {
146 processVariables.put(PROCESS_VARIABLE_INCOMING_SOURCE, originatingEndpoint);
147 }
148 }
149 }
150
151 String processIdField = getProcessIdField();
152 if (StringUtils.isEmpty(processIdField))
153 {
154 processIdField = PROPERTY_PROCESS_ID;
155 }
156
157 Object processId;
158 processId = event.getMessage().getSessionProperty(processIdField);
159 if (processId == null)
160 {
161 processId = event.getMessage().getInvocationProperty(processIdField);
162 }
163 if (processId == null)
164 {
165 processId = event.getMessage().getInboundProperty(processIdField);
166 }
167 processVariables.remove(processIdField);
168
169
170 String action = event.getMessage().getInvocationProperty(PROPERTY_ACTION, ACTION_ADVANCE);
171 processVariables.remove(PROPERTY_ACTION);
172
173 Object transition = event.getMessage().getInvocationProperty(PROPERTY_TRANSITION);
174 processVariables.remove(PROPERTY_TRANSITION);
175
176
177
178 logger.debug("Message received: payload = " + event.getMessage().getPayload().getClass().getName() + " processType = " + name + " processId = " + processId + " action = " + action);
179
180
181 if (processId == null || action.equals(ACTION_START))
182 {
183 process = getBpms().startProcess(name, transition, processVariables);
184 if ((process != null) && logger.isInfoEnabled())
185 {
186 logger.info("New process started, ID = " + getBpms().getId(process));
187 }
188 }
189
190
191 else if (action.equals(ACTION_UPDATE))
192 {
193 if (processId != null)
194 {
195 process = getBpms().updateProcess(processId, processVariables);
196 if ((process != null) && logger.isInfoEnabled())
197 {
198 logger.info("Process variables updated, ID = " + getBpms().getId(process));
199 }
200 }
201 else
202 {
203 throw new IllegalArgumentException("Process ID is missing, cannot update process.");
204 }
205 }
206
207
208 else if (action.equals(ACTION_ABORT))
209 {
210 if (processId != null)
211 {
212 getBpms().abortProcess(processId);
213 process = NullPayload.getInstance();
214 logger.info("Process aborted, ID = " + processId);
215 }
216 else
217 {
218 throw new IllegalArgumentException("Process ID is missing, cannot abort process.");
219 }
220 }
221
222
223 else
224 {
225 if (processId != null)
226 {
227 process = getBpms().advanceProcess(processId, transition, processVariables);
228 if ((process != null) && logger.isInfoEnabled())
229 {
230 logger.info("Process advanced, ID = " + getBpms().getId(process)
231 + ", new state = " + getBpms().getState(process));
232 }
233 }
234 else
235 {
236 throw new IllegalArgumentException("Process ID is missing, cannot advance process.");
237 }
238 }
239
240 return process;
241 }
242
243 protected void populateProcessVariables(MuleEvent event, Map processVariables, PropertyScope propertyScope)
244 {
245 for (String propertyName : event.getMessage().getPropertyNames(propertyScope))
246 {
247
248 if (!propertyName.equals(MuleProperties.MULE_SESSION_PROPERTY))
249 {
250 processVariables.put(propertyName, event.getMessage().getProperty(propertyName, propertyScope));
251 }
252 }
253 }
254
255 public MuleMessage generateMessage(String endpoint, Object payload, Map messageProperties, MessageExchangePattern exchangePattern) throws MuleException
256 {
257 MuleMessage message;
258 if (payload instanceof MuleMessage)
259 {
260 message = (MuleMessage) payload;
261 }
262 else
263 {
264 message = new DefaultMuleMessage(payload, flowConstruct.getMuleContext());
265 }
266 message.addProperties(messageProperties, PropertyScope.INBOUND);
267 message.addProperties(messageProperties, PropertyScope.INVOCATION);
268
269
270 EndpointBuilder endpointBuilder = flowConstruct.getMuleContext().getRegistry().lookupEndpointFactory().getEndpointBuilder(endpoint);
271 endpointBuilder.setExchangePattern(exchangePattern);
272 OutboundEndpoint ep = endpointBuilder.buildOutboundEndpoint();
273
274 DefaultMuleEvent event = new DefaultMuleEvent(message, ep, new DefaultMuleSession(flowConstruct, flowConstruct.getMuleContext()));
275
276
277 RequestContext.setEvent(event);
278 if (messageProperties.get(PROPERTY_PROCESS_TYPE) != null)
279 {
280 event.getMessage().setSessionProperty(PROPERTY_PROCESS_TYPE, messageProperties.get(PROPERTY_PROCESS_TYPE));
281 }
282 if (messageProperties.get(PROPERTY_PROCESS_ID) != null)
283 {
284 event.getMessage().setSessionProperty(PROPERTY_PROCESS_ID, messageProperties.get(PROPERTY_PROCESS_ID));
285 }
286
287 MuleEvent resultEvent = ep.process(event);
288
289 MuleMessage response = null;
290 if (resultEvent != null)
291 {
292 response = resultEvent.getMessage();
293 if (response.getExceptionPayload() != null)
294 {
295 throw new DispatchException(MessageFactory.createStaticMessage("Unable to send or route message"), event, ep, response.getExceptionPayload().getRootException());
296 }
297 }
298 return response;
299 }
300
301 public String getProcessIdField()
302 {
303 return processIdField;
304 }
305
306 public BPMS getBpms()
307 {
308 return bpms;
309 }
310
311 public String getResource()
312 {
313 return resource;
314 }
315
316 public String getName()
317 {
318 return name;
319 }
320 }
321
322