001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.servicemix.osworkflow;
018
019 import java.util.HashMap;
020
021 import javax.jbi.messaging.ExchangeStatus;
022 import javax.jbi.messaging.InOnly;
023 import javax.jbi.messaging.InOut;
024 import javax.jbi.messaging.MessageExchange;
025 import javax.jbi.messaging.MessageExchange.Role;
026 import javax.jbi.messaging.MessagingException;
027 import javax.jbi.messaging.NormalizedMessage;
028 import javax.jbi.messaging.RobustInOnly;
029 import javax.xml.namespace.QName;
030 import javax.xml.transform.Source;
031
032 import org.apache.servicemix.common.endpoints.ProviderEndpoint;
033 import org.apache.servicemix.common.EndpointSupport;
034 import org.apache.servicemix.jbi.jaxp.SourceTransformer;
035 import org.apache.servicemix.executors.Executor;
036
037 /**
038 * @org.apache.xbean.XBean element="endpoint"
039 *
040 * @author lhe
041 */
042 public class OSWorkflowEndpoint extends ProviderEndpoint {
043
044 private static final long TIME_OUT = 30000;
045
046 private String workflowName;
047
048 private String caller;
049
050 private int action;
051
052 private Executor executor;
053
054 private SourceTransformer sourceTransformer = new SourceTransformer();
055
056 public void start() throws Exception {
057 super.start();
058 OSWorkflowComponent component = (OSWorkflowComponent) getServiceUnit().getComponent();
059 executor = component.getExecutorFactory().createExecutor("component." + component.getComponentName() + "." + EndpointSupport.getKey(this));
060 }
061
062 public void stop() throws Exception {
063 executor.shutdown();
064 super.stop();
065 }
066
067 /*
068 * (non-Javadoc)
069 *
070 * @see org.apache.servicemix.common.ExchangeProcessor#process(javax.jbi.messaging.MessageExchange)
071 */
072 public void process(MessageExchange exchange) throws Exception {
073 if (exchange == null) {
074 return;
075 }
076
077 // The component acts as a consumer, this means this exchange is
078 // received because
079 // we sent it to another component. As it is active, this is either an
080 // out or a fault
081 // If this component does not create / send exchanges, you may just
082 // throw an
083 // UnsupportedOperationException
084 if (exchange.getRole() == Role.CONSUMER) {
085 onConsumerExchange(exchange);
086 } else if (exchange.getRole() == MessageExchange.Role.PROVIDER) {
087 // The component acts as a provider, this means that another component
088 // has requested our
089 // service
090 // As this exchange is active, this is either an in or a fault (out are
091 // send by this
092 // component)
093 onProviderExchange(exchange);
094 } else {
095 // Unknown role
096 throw new MessagingException("OSWorkflowEndpoint.onMessageExchange(): Unknown role: "
097 + exchange.getRole());
098 }
099 }
100
101 /**
102 * handles the incoming consumer messages
103 *
104 * @param exchange
105 * @throws MessagingException
106 */
107 protected void onConsumerExchange(MessageExchange exchange)
108 throws MessagingException {
109 // Out message
110 if (exchange.getMessage("out") != null) {
111 done(exchange);
112 } else if (exchange.getFault() != null) {
113 //Fault message
114 done(exchange);
115 } else {
116 //This is not compliant with the default MEPs
117 throw new MessagingException(
118 "OSWorkflowEndpoint.onConsumerExchange(): Consumer exchange is ACTIVE, but no out or fault is provided");
119 }
120 }
121
122 /**
123 * handles the incoming provider messages
124 *
125 * @param exchange
126 * @throws MessagingException
127 */
128 protected void onProviderExchange(MessageExchange exchange)
129 throws MessagingException {
130
131 if (exchange.getStatus() == ExchangeStatus.DONE) {
132 //Exchange is finished
133 return;
134 } else if (exchange.getStatus() == ExchangeStatus.ERROR) {
135 //Exchange has been aborted with an exception
136 return;
137 } else if (exchange.getFault() != null) {
138 //Fault message
139 done(exchange);
140 } else {
141 NormalizedMessage in = exchange.getMessage("in");
142
143 if (in == null) {
144 // no in message - strange
145 throw new MessagingException(
146 "OSWorkflowEndpoint.onProviderExchange(): Exchange has no IN message");
147 } else {
148 // create a new workflow object
149 OSWorkflow osWorkflow = new OSWorkflow(this, this.workflowName,
150 this.action, new HashMap(), this.caller, exchange);
151
152 executor.execute(osWorkflow);
153 }
154 }
155 }
156
157 /**
158 * sends the given DOMSource as message to the given service (inOnly)
159 *
160 * @param service
161 * the service name to send the message to
162 * @param source
163 * the source to put in the in message content
164 * @return true on sucessful delivering or false on failure
165 * @throws MessagingException
166 * on any messaging exception
167 */
168 public boolean sendMessage(QName service, Source source)
169 throws MessagingException {
170 InOnly inOnly = getChannel().createExchangeFactoryForService(service).createInOnlyExchange();
171 NormalizedMessage msg = inOnly.createMessage();
172 msg.setContent(source);
173 inOnly.setInMessage(msg);
174 if (getChannel().sendSync(inOnly)) {
175 return inOnly.getStatus() == ExchangeStatus.DONE;
176 } else {
177 return false;
178 }
179 }
180
181 /**
182 * sends the given DOMSource as message to the given service (inOut)
183 *
184 * @param service
185 * the service name to send the message to
186 * @param source
187 * the source to put in the in message content
188 * @return the DOMSource of the out message or null
189 * @throws MessagingException
190 * on any messaging exception
191 */
192 public Source sendRequest(QName service, Source source)
193 throws MessagingException {
194 InOut inOut = getChannel().createExchangeFactoryForService(service).createInOutExchange();
195 NormalizedMessage msg = inOut.createMessage();
196 msg.setContent(source);
197 inOut.setInMessage(msg);
198
199 if (getChannel().sendSync(inOut)) {
200 try {
201 Source result = sourceTransformer.toDOMSource(inOut.getOutMessage().getContent());
202 done(inOut);
203 return result;
204 } catch (Exception ex) {
205 ex.printStackTrace();
206 return null;
207 }
208 } else {
209 return null;
210 }
211 }
212
213 /**
214 * sends the given DOMSource as message to the given service (inOut)
215 *
216 * @param service
217 * the service name to send the message to
218 * @param source
219 * the source to put in the in message content
220 * @return the DOMSource of the out message or null
221 * @throws MessagingException
222 * on any messaging exception
223 */
224 public MessageExchange sendRawInOutRequest(QName service, Source source)
225 throws MessagingException {
226 InOut inOut = getChannel().createExchangeFactoryForService(service).createInOutExchange();
227 NormalizedMessage msg = inOut.createMessage();
228 msg.setContent(source);
229 inOut.setInMessage(msg);
230 if (getChannel().sendSync(inOut)) {
231 return inOut;
232 } else {
233 return null;
234 }
235 }
236
237 /**
238 * creates a msg object
239 *
240 * @param qname
241 * the service which will be the receiver
242 * @param inOut
243 * should it be inOut or InOnly
244 * @return the created exchange
245 * @throws MessagingException
246 */
247 public MessageExchange getNewExchange(QName qname, boolean inOut)
248 throws MessagingException {
249 MessageExchange exchange = null;
250
251 if (inOut) {
252 exchange = getChannel().createExchangeFactoryForService(qname).createInOutExchange();
253 } else {
254 exchange = getChannel().createExchangeFactoryForService(qname).createInOnlyExchange();
255 }
256
257 return exchange;
258 }
259
260 /**
261 * sends a done to the channel
262 *
263 * @param ex
264 * @throws MessagingException
265 */
266 public void done(MessageExchange ex) throws MessagingException {
267 super.done(ex);
268 }
269
270 /**
271 * sends a msg to the channel
272 *
273 * @param ex
274 * @param sync
275 * @throws MessagingException
276 */
277 public void send(MessageExchange ex, boolean sync)
278 throws MessagingException {
279 if (sync) {
280 getChannel().sendSync(ex, TIME_OUT);
281 } else {
282 getChannel().send(ex);
283 }
284 }
285
286 /**
287 * sends a error to the channel
288 *
289 * @param ex
290 * @throws MessagingException
291 */
292 public void fail(MessageExchange ex) throws MessagingException {
293 super.fail(ex, new Exception("Failure"));
294 }
295
296 /**
297 * @return the workflowName
298 */
299 public String getWorkflowName() {
300 return this.workflowName;
301 }
302
303 /**
304 * @param workflowName
305 * the workflowName to set
306 */
307 public void setWorkflowName(String workflowName) {
308 this.workflowName = workflowName;
309 }
310
311 /**
312 * @return the caller
313 */
314 public String getCaller() {
315 return this.caller;
316 }
317
318 /**
319 * @param caller
320 * the caller to set
321 */
322 public void setCaller(String caller) {
323 this.caller = caller;
324 }
325
326 /**
327 * @return the action
328 */
329 public int getAction() {
330 return this.action;
331 }
332
333 /**
334 * @param action
335 * the action to set
336 */
337 public void setAction(int action) {
338 this.action = action;
339 }
340
341 /**
342 * init actions
343 */
344 public void preWorkflow() {
345 // nothing for now
346 }
347
348 /**
349 * cleanup action
350 */
351 public void postWorkflow() {
352 // nothing for now
353 }
354
355 }