View Javadoc

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