View Javadoc

1   /*
2    * $Id: ProcessConnector.java 11541 2008-04-08 18:09:49Z tcarlson $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.transport.bpm;
12  
13  import org.mule.api.MuleException;
14  import org.mule.api.MuleMessage;
15  import org.mule.api.config.ConfigurationException;
16  import org.mule.api.config.MuleProperties;
17  import org.mule.api.lifecycle.InitialisationException;
18  import org.mule.config.i18n.MessageFactory;
19  import org.mule.module.client.MuleClient;
20  import org.mule.transport.AbstractConnector;
21  import org.mule.util.StringUtils;
22  
23  import java.util.Map;
24  
25  /**
26   * The BPM provider allows Mule events to initiate and/or advance processes in an
27   * external or embedded Business Process Management System (BPMS). It also allows
28   * executing processes to generate Mule events.
29   */
30  public class ProcessConnector extends AbstractConnector implements MessageService
31  {
32  
33      /** The underlying BPMS */
34      protected BPMS bpms;
35  
36      /** This field will be used to correlate messages with processes. */
37      protected String processIdField;
38  
39      /**
40       * The global receiver allows an endpoint of type "bpm://*" to receive any
41       * incoming message to the BPMS, regardless of the process. If this is false, the
42       * process name must be specified for each endpoint, e.g. "bpm://MyProcess" will
43       * only receive messages for the process "MyProcess".
44       */
45      protected boolean allowGlobalReceiver = false;
46  
47      /**
48       * If false, any message generated by the process is routed from the service on 
49       * which it is received.  If true, a process can send messages to any endpoint
50       * on any service.
51       */
52      protected boolean allowGlobalDispatcher = false;
53  
54      public static final String BPM_PROPERTY_PREFIX = "BPM_";
55      
56      public static final String PROPERTY_ENDPOINT = 
57          MuleProperties.PROPERTY_PREFIX + BPM_PROPERTY_PREFIX + "ENDPOINT";
58      public static final String PROPERTY_PROCESS_TYPE = 
59          MuleProperties.PROPERTY_PREFIX + BPM_PROPERTY_PREFIX + "PROCESS_TYPE";
60      public static final String PROPERTY_PROCESS_ID = 
61          MuleProperties.PROPERTY_PREFIX + BPM_PROPERTY_PREFIX + "PROCESS_ID";
62      public static final String PROPERTY_ACTION = 
63          MuleProperties.PROPERTY_PREFIX + BPM_PROPERTY_PREFIX + "ACTION";
64      public static final String PROPERTY_TRANSITION = 
65          MuleProperties.PROPERTY_PREFIX + BPM_PROPERTY_PREFIX + "TRANSITION";
66      public static final String PROPERTY_PROCESS_STARTED = 
67          MuleProperties.PROPERTY_PREFIX + BPM_PROPERTY_PREFIX + "STARTED";
68      
69      public static final String ACTION_START = "start";
70      public static final String ACTION_ADVANCE = "advance";
71      public static final String ACTION_UPDATE = "update";
72      public static final String ACTION_ABORT = "abort";
73      
74      public static final String PROCESS_VARIABLE_INCOMING = "incoming";
75      public static final String PROCESS_VARIABLE_INCOMING_SOURCE = "incomingSource";
76      public static final String PROCESS_VARIABLE_DATA = "data";
77  
78      public static final String PROTOCOL = "bpm";
79      public static final String GLOBAL_RECEIVER = PROTOCOL + "://*";
80  
81      private MuleClient muleClient = null;
82  
83      public String getProtocol()
84      {
85          return PROTOCOL;
86      }
87  
88      protected void doInitialise() throws InitialisationException
89      {
90          try
91          {
92              if (bpms == null)
93              {
94                  throw new ConfigurationException(
95                      MessageFactory.createStaticMessage("The bpms property must be set for this connector."));
96              }
97  
98              // Set a callback so that the BPMS may generate messages within Mule.
99              bpms.setMessageService(this);
100             
101             // The MuleClient is used as a global dispatcher.  
102             // TODO MULE-1221 It would be cleaner to use something like the dynamic:// transport
103             if ((allowGlobalDispatcher == true) && (muleClient == null))
104             {
105                 muleClient = new MuleClient(muleContext);
106             }
107         }
108         catch (Exception e)
109         {
110             throw new InitialisationException(e, this);
111         }
112     }
113 
114     protected void doDispose()
115     {
116         // template method
117     }
118 
119     protected void doConnect() throws Exception
120     {
121         // template method
122     }
123 
124     protected void doDisconnect() throws Exception
125     {
126         // template method
127     }
128 
129     protected void doStart() throws MuleException
130     {
131         // template method
132     }
133 
134     protected void doStop() throws MuleException
135     {
136         // template method
137     }
138 
139     /**
140      * This method looks for a receiver based on the process name and ID. It searches
141      * iteratively from the narrowest scope (match process name and ID) to the widest
142      * scope (match neither - global receiver) possible.
143      * 
144      * @return ProcessMessageReceiver or null if no match is found
145      */
146     public ProcessMessageReceiver lookupReceiver(String processName, Object processId)
147     {
148         ProcessMessageReceiver receiver = (ProcessMessageReceiver)lookupReceiver(toUrl(processName, processId));
149         if (receiver == null)
150         {
151             receiver = (ProcessMessageReceiver)lookupReceiver(toUrl(processName, null));
152         }
153         if (receiver == null)
154         {
155             receiver = (ProcessMessageReceiver)lookupReceiver(toUrl(null, null));
156         }
157         return receiver;
158     }
159 
160     /**
161      * Generate a URL based on the process name and ID such as "bpm://myProcess/2342"
162      * If the parameters are missing, and <code>allowGlobalReceiver</code> is true,
163      * the GLOBAL_RECEIVER is returned.
164      */
165     public String toUrl(String processName, Object processId)
166     {
167         String url = getProtocol() + "://";
168         if (StringUtils.isNotEmpty(processName))
169         {
170             url += processName;
171             if (processId != null)
172             {
173                 url += "/" + processId;
174             }
175         }
176         else if (isAllowGlobalReceiver())
177         {
178             return GLOBAL_RECEIVER;
179         }
180         else
181         {
182             throw new IllegalArgumentException(
183                 "No valid URL could be created for the given process name and ID: processName = " + processName + ", processId = " + processId);
184         }
185         return url;
186     }
187 
188     public MuleMessage generateMessage(String endpoint,
189                                       Object payloadObject,
190                                       Map messageProperties,
191                                       boolean synchronous) throws Exception
192     {
193         String processName = (String)messageProperties.get(ProcessConnector.PROPERTY_PROCESS_TYPE);
194         Object processId = messageProperties.get(ProcessConnector.PROPERTY_PROCESS_ID);
195 
196         // Look up a receiver for this process.
197         ProcessMessageReceiver receiver = lookupReceiver(processName, processId);
198         if (receiver == null)
199         {
200             throw new ConfigurationException(MessageFactory
201                 .createStaticMessage("No corresponding receiver found for processName = " + processName
202                                 + ", processId = " + processId));
203         }
204 
205         if (synchronous)
206         {
207             // Send the process-generated Mule message synchronously.
208             return receiver.generateSynchronousEvent(endpoint, payloadObject, messageProperties);
209         }
210         else
211         {
212             // Dispatch the process-generated Mule message asynchronously.
213             receiver.generateAsynchronousEvent(endpoint, payloadObject, messageProperties);
214             return null;
215         }
216     }
217 
218     // //////////////////////////////////////////////////////////////////////////
219     // Getters and Setters
220     // //////////////////////////////////////////////////////////////////////////
221 
222     public BPMS getBpms()
223     {
224         return bpms;
225     }
226 
227     public void setBpms(BPMS bpms)
228     {
229         this.bpms = bpms;
230     }
231 
232     public MuleClient getMuleClient()
233     {
234         return muleClient;
235     }
236 
237     public boolean isAllowGlobalDispatcher()
238     {
239         return allowGlobalDispatcher;
240     }
241 
242     public void setAllowGlobalDispatcher(boolean allowGlobalDispatcher)
243     {
244         this.allowGlobalDispatcher = allowGlobalDispatcher;
245     }
246 
247     public boolean isAllowGlobalReceiver()
248     {
249         return allowGlobalReceiver;
250     }
251 
252     public void setAllowGlobalReceiver(boolean allowGlobalReceiver)
253     {
254         this.allowGlobalReceiver = allowGlobalReceiver;
255     }
256 
257     public String getProcessIdField()
258     {
259         return processIdField;
260     }
261 
262     public void setProcessIdField(String processIdField)
263     {
264         this.processIdField = processIdField;
265     }
266 }