001: /*
002: * ====================================================================
003: *
004: * XFLOW - Process Management System
005: * Copyright (C) 2003 Rob Tan
006: * All rights reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: *
012: * 1. Redistributions of source code must retain the above copyright
013: * notice, this list of conditions, and the following disclaimer.
014: *
015: * 2. Redistributions in binary form must reproduce the above copyright
016: * notice, this list of conditions, and the disclaimer that follows
017: * these conditions in the documentation and/or other materials
018: * provided with the distribution.
019: *
020: * 3. The name "XFlow" must not be used to endorse or promote products
021: * derived from this software without prior written permission. For
022: * written permission, please contact rcktan@yahoo.com
023: *
024: * 4. Products derived from this software may not be called "XFlow", nor
025: * may "XFlow" appear in their name, without prior written permission
026: * from the XFlow Project Management (rcktan@yahoo.com)
027: *
028: * In addition, we request (but do not require) that you include in the
029: * end-user documentation provided with the redistribution and/or in the
030: * software itself an acknowledgement equivalent to the following:
031: * "This product includes software developed by the
032: * XFlow Project (http://xflow.sourceforge.net/)."
033: * Alternatively, the acknowledgment may be graphical using the logos
034: * available at http://xflow.sourceforge.net/
035: *
036: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
037: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
038: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
039: * DISCLAIMED. IN NO EVENT SHALL THE XFLOW AUTHORS OR THE PROJECT
040: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
041: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
042: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
043: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
044: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
045: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
046: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
047: * SUCH DAMAGE.
048: *
049: * ====================================================================
050: * This software consists of voluntary contributions made by many
051: * individuals on behalf of the XFlow Project and was originally
052: * created by Rob Tan (rcktan@yahoo.com)
053: * For more information on the XFlow Project, please see:
054: * <http://xflow.sourceforge.net/>.
055: * ====================================================================
056: */
057: package xflow.client;
058:
059: import java.util.*;
060: import java.io.*;
061: import javax.jms.*;
062: import javax.naming.*;
063:
064: import xflow.common.*;
065: import xflow.protocol.*;
066: import xflow.util.*;
067: import xflow.messaging.*;
068: import xflow.security.*;
069:
070: import org.apache.log4j.Logger;
071:
072: /**
073: * A WorkflowProcess receives work items from the XFlow system and
074: * "works" on them. It is bound or associated to a node in the workflow model.
075: */
076: public class WorkflowProcess implements MessageListener {
077:
078: private String workflowName;
079: private int workflowVersion;
080: private String procName;
081: private InboxMessageListener mlistener;
082: private User user;
083: private JMSSubscriber subscriber;
084:
085: private static Logger log = Logger.getLogger(WorkflowProcess.class);
086:
087: public void onMessage(Message msg) {
088:
089: WorkItem workItem = null;
090:
091: try {
092: BytesMessage bytesMessage = (BytesMessage) msg;
093: byte[] barr = new byte[10000];
094: bytesMessage.readBytes(barr);
095:
096: ByteArrayInputStream in = new ByteArrayInputStream(barr);
097: ObjectInputStream sin = new ObjectInputStream(in);
098: workItem = (WorkItem) sin.readObject();
099: } catch (Throwable t) {
100: log.error("onMessage error", t);
101: }
102:
103: mlistener.onMessage(workItem);
104: }
105:
106: /**
107: * WorkflowProcess constructor
108: *
109: * @param wfName the workflow name
110: * @param wfVersion the workflow version - set to -1 if the latest version is to be used
111: * @param processName the process name - must be the name of a valid process node in the workflow model
112: * @param listener the inbox listener for asynchronous delivery of work items - may be null
113: * @param user the user
114: * @exception XflowException
115: */
116: public WorkflowProcess(String wfName, int wfVersion,
117: String processName, InboxMessageListener listener, User u)
118: throws XflowException {
119:
120: try {
121: JMSTopicConnection.initialize();
122: } catch (JMSException e) {
123: throw new XflowException(e.getMessage());
124: }
125:
126: workflowName = wfName;
127: workflowVersion = wfVersion;
128: procName = processName;
129: mlistener = listener;
130: user = u;
131:
132: // Validate workflowName and processName
133: ValidateProcessRequest req = new ValidateProcessRequest();
134: req.workflowName = workflowName;
135: req.workflowVersion = workflowVersion;
136: req.processName = procName;
137: req.user = user;
138:
139: ValidateProcessResponse resp = (ValidateProcessResponse) sendRequest(req);
140: if (!resp.ok) {
141: throw new XflowException(
142: "Unrecognized process name in specified workflow.");
143: }
144:
145: // Start a subscription for inbox events
146: if (listener != null) {
147: subscriber = new JMSSubscriber(this ,
148: XflowConstants.XFLOW_TOPIC, "ProcessName in ('"
149: + workflowName + procName + "')");
150: }
151: }
152:
153: /**
154: * Gets a list of work items from this process's inbox.
155: *
156: * @return A list of WorkItem objects
157: * @exception XflowException
158: */
159: public Vector getWorkItems() throws XflowException {
160:
161: GetWorkItemsRequest req = new GetWorkItemsRequest();
162: req.workflowName = workflowName;
163: req.workflowVersion = workflowVersion;
164: req.processName = procName;
165: req.user = user;
166: GetWorkItemsResponse resp = (GetWorkItemsResponse) sendRequest(req);
167: return resp.workItems;
168: }
169:
170: /**
171: * Gets the next work item (in First-In-First-Out order) from the inbox
172: *
173: * @return A WorkItem object or null - if there are no work items.
174: * @exception XflowException
175: */
176: public WorkItem getNextWorkItem() throws XflowException {
177:
178: GetNextWorkItemRequest req = new GetNextWorkItemRequest();
179: req.workflowName = workflowName;
180: req.workflowVersion = workflowVersion;
181: req.processName = procName;
182: req.user = user;
183: GetNextWorkItemResponse resp = (GetNextWorkItemResponse) sendRequest(req);
184: return resp.workItem;
185: }
186:
187: /**
188: * Gets a work item with a specific work item ID from the inbox
189: *
190: * @param The work item ID
191: * @return A WorkItem object or null - if there is no such work item
192: * @exception XflowException
193: */
194: public WorkItem getWorkItem(WorkItemId workItemId)
195: throws XflowException {
196:
197: GetWorkItemRequest req = new GetWorkItemRequest();
198: req.workflowName = workflowName;
199: req.workflowVersion = workflowVersion;
200: req.processName = procName;
201: req.user = user;
202: req.workItemId = workItemId;
203: GetWorkItemResponse resp = (GetWorkItemResponse) sendRequest(req);
204: return resp.workItem;
205: }
206:
207: /**
208: * Completes a work item. This is typically invoked by a workflow process after
209: * it is done with its processing of the work item.
210: *
211: * @param The work item ID
212: * @exception XflowException
213: */
214: public void completeWorkItem(WorkItem workItem)
215: throws XflowException {
216:
217: CompleteWorkItemRequest req = new CompleteWorkItemRequest();
218: req.workflowName = workflowName;
219: req.workflowVersion = workflowVersion;
220: req.processName = procName;
221: req.user = user;
222: req.workItem = workItem;
223: CompleteWorkItemResponse resp = (CompleteWorkItemResponse) sendRequest(req);
224: }
225:
226: private static Response sendRequest(Request req)
227: throws XflowException {
228:
229: req.replyName = Util.generateUniqueStringId();
230: try {
231: Response resp = SynchQueueMessaging.sendRequest(req);
232: if (resp.responseCode != Response.SUCCESS) {
233: throw new XflowException(resp.message);
234: }
235: return resp;
236: } catch (Exception t) {
237: throw new XflowException(t.getMessage());
238: }
239: }
240: }
|