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.Map;
020
021 import javax.jbi.messaging.InOnly;
022 import javax.jbi.messaging.MessageExchange;
023 import javax.jbi.messaging.RobustInOnly;
024
025
026 import com.opensymphony.workflow.InvalidInputException;
027 import com.opensymphony.workflow.InvalidRoleException;
028 import com.opensymphony.workflow.Workflow;
029 import com.opensymphony.workflow.WorkflowException;
030 import com.opensymphony.workflow.basic.BasicWorkflow;
031 import com.opensymphony.workflow.config.DefaultConfiguration;
032
033
034 import org.apache.commons.logging.Log;
035 import org.apache.commons.logging.LogFactory;
036 /**
037 * @author lhe
038 */
039 public class OSWorkflow implements Runnable {
040
041
042 public static final String KEY_EXCHANGE = "exchange";
043
044 public static final String KEY_IN_MESSAGE = "in-message";
045
046 public static final String KEY_ENDPOINT = "endpoint";
047
048 public static final String KEY_CALLER = "caller";
049
050 public static final String KEY_ASYNC_PROCESSING = "asynchronous";
051
052 private static Log log = LogFactory.getLog(OSWorkflow.class);
053
054 private Workflow osWorkflowInstance;
055
056 private String caller;
057
058 private String osWorkflowName;
059
060 private Map map;
061
062 private int action = -1;
063
064 private long workflowId = -1L;
065
066 private boolean finished;
067
068 private boolean aborted;
069
070 private OSWorkflowEndpoint endpoint;
071
072 private MessageExchange exchange;
073
074 /**
075 * creates and initializes a new workflow object
076 *
077 * @param ep
078 * the endpoint reference
079 * @param workflowName
080 * the unique workflow name as defined in workflows.xml
081 * @param action
082 * the initial action
083 * @param map
084 * the value map
085 * @param caller
086 * the caller
087 * @param exchange
088 * the received message exchange
089 */
090 public OSWorkflow(OSWorkflowEndpoint ep, String workflowName, int action,
091 Map map, String caller, MessageExchange exchange) {
092
093 this.endpoint = ep; // remember the endpoint which called the osworkflow
094 this.osWorkflowName = workflowName;
095 this.osWorkflowInstance = null;
096 this.action = action;
097 this.map = map;
098 this.caller = caller;
099 this.exchange = exchange;
100
101 // now fill the transient vars with some useful objects
102 this.map.put(KEY_ENDPOINT, this.endpoint);
103 this.map.put(KEY_CALLER, this.caller);
104 this.map.put(KEY_IN_MESSAGE, this.exchange.getMessage("in"));
105 this.map.put(KEY_EXCHANGE, this.exchange);
106 this.map.put(KEY_ASYNC_PROCESSING, this.exchange instanceof InOnly || this.exchange instanceof RobustInOnly);
107 }
108
109 /**
110 * initializes the workflow and a default config
111 *
112 * @return the unique workflow id
113 */
114 private long createWorkflow() throws InvalidRoleException,
115 InvalidInputException, WorkflowException {
116 this.osWorkflowInstance = new BasicWorkflow(this.caller);
117 DefaultConfiguration config = new DefaultConfiguration();
118 this.osWorkflowInstance.setConfiguration(config);
119 long wfId = this.osWorkflowInstance.initialize(this.osWorkflowName, this.action, this.map);
120 return wfId;
121 }
122
123 /*
124 * (non-Javadoc)
125 *
126 * @see java.lang.Runnable#run()
127 */
128 public void run() {
129 // call the endpoint method for init actions
130 this.endpoint.preWorkflow();
131
132 if (log.isDebugEnabled()) {
133 log.debug("Starting workflow...");
134 log.debug("Name: " + this.osWorkflowName);
135 log.debug("Action: " + this.action);
136 log.debug("Caller: " + this.caller);
137 log.debug("Map: " + this.map);
138 }
139
140 // loop as long as there are more actions to do and the workflow is not
141 // finished or aborted
142 while (!finished && !aborted) {
143 // initial creation
144 if (this.osWorkflowInstance == null) {
145 try {
146 this.workflowId = createWorkflow();
147 } catch (Exception ex) {
148 log.error("Error creating the workflow", ex);
149 aborted = true;
150 break;
151 }
152 }
153
154 // determine the available actions
155 int[] availableActions = this.osWorkflowInstance.getAvailableActions(this.workflowId, this.map);
156
157 // check if there are more actions available
158 if (availableActions.length == 0) {
159 // no, no more actions available - workflow finished
160 log.debug("No more actions. Workflow is finished...");
161 this.finished = true;
162 } else {
163 // get first available action to execute
164 int nextAction = availableActions[0];
165
166 log.debug("call action " + nextAction);
167 try {
168 // call the action
169 this.osWorkflowInstance.doAction(this.workflowId,nextAction, this.map);
170 } catch (InvalidInputException iiex) {
171 log.error(iiex);
172 aborted = true;
173 } catch (WorkflowException wfex) {
174 log.error(wfex);
175 aborted = true;
176 }
177 }
178 }
179
180 if (log.isDebugEnabled()) {
181 log.debug("Stopping workflow...");
182 log.debug("Name: " + this.osWorkflowName);
183 log.debug("Action: " + this.action);
184 log.debug("Caller: " + this.caller);
185 log.debug("Map: " + this.map);
186 log.debug("WorkflowId: " + this.workflowId);
187 log.debug("End state: " + (finished ? "Finished" : "Aborted"));
188 }
189
190 // call the endpoint method for cleanup actions or message exchange
191 this.endpoint.postWorkflow();
192 }
193 }