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:
058: package xflow.server.controller;
059:
060: import java.io.*;
061: import java.util.*;
062: import java.lang.*;
063: import java.sql.*;
064: import org.apache.log4j.Logger;
065: import xflow.common.*;
066: import xflow.protocol.*;
067: import xflow.util.*;
068: import xflow.server.util.*;
069:
070: import org.apache.log4j.Logger;
071:
072: public class WorkflowP {
073:
074: private static Logger log = Logger.getLogger(WorkflowP.class);
075:
076: public static int saveDB(int graphId, String workflowName,
077: String initiator, int parentWorkflowId)
078: throws XflowException {
079:
080: int wfId = 0;
081: Connection con = null;
082: Statement s = null;
083:
084: String pWfId = "null";
085: if (parentWorkflowId != -1) {
086: pWfId = "" + parentWorkflowId;
087: }
088:
089: try {
090: con = Persistence.getConnection();
091: s = con.createStatement();
092:
093: // Create and save workflow instance
094: String timeStarted = DateUtil.getTimestamp();
095: String sql = "insert into workflow values (null, "
096: + graphId + ", '" + initiator + "', true, '"
097: + timeStarted + "', null, 'RUNNING' ," + pWfId
098: + ")";
099: log.info(sql);
100: s.execute(sql);
101:
102: sql = "select max(workflowId), workflowId from workflow";
103: ResultSet rs = s.executeQuery(sql);
104: if (rs.next()) {
105: wfId = rs.getInt("workflowId");
106: } else {
107: throw new XflowException("Unable to obtain workflowId");
108: }
109: } catch (Exception e) {
110: e.printStackTrace();
111: throw new XflowException(
112: "Failed to save workflow in database");
113: } finally {
114: if (s != null) {
115: try {
116: s.close();
117: } catch (Exception e) {
118: e.printStackTrace();
119: }
120: }
121: if (con != null) {
122: try {
123: con.close();
124: } catch (Exception e) {
125: }
126: }
127: }
128: return wfId;
129: }
130:
131: public static int getGraphId(int workflowId) throws XflowException {
132:
133: int gid = -1;
134: Connection con = null;
135: Statement s = null;
136: try {
137: con = Persistence.getConnection();
138: s = con.createStatement();
139:
140: String sql = "select gid from workflow where workflowId = "
141: + workflowId;
142: log.info(sql);
143: ResultSet rs = s.executeQuery(sql);
144: if (rs.next()) {
145: gid = rs.getInt("gid");
146: }
147: } catch (Exception e) {
148: e.printStackTrace();
149: throw new XflowException(
150: "Failed to get gid from workflow in database");
151: } finally {
152: if (s != null) {
153: try {
154: s.close();
155: } catch (Exception e) {
156: e.printStackTrace();
157: }
158: }
159: if (con != null) {
160: try {
161: con.close();
162: } catch (Exception e) {
163: }
164: }
165: }
166: return gid;
167: }
168:
169: public static HashMap getWorkflows(String filter)
170: throws XflowException {
171:
172: HashMap workflows = new HashMap();
173: Connection con = null;
174: Statement s = null;
175: try {
176: con = Persistence.getConnection();
177: s = con.createStatement();
178:
179: String sql = "select workflowId from workflow " + filter;
180: log.info(sql);
181: ResultSet rs = s.executeQuery(sql);
182: while (rs.next()) {
183: int wfId = rs.getInt("workflowId");
184: WorkflowId workflowId = new WorkflowId(wfId);
185: Integer key = new Integer(workflowId.getValue());
186: workflows.put(key, workflowId);
187: }
188: } catch (Exception e) {
189: e.printStackTrace();
190: throw new XflowException(
191: "Failed to get workflows from database");
192: } finally {
193: if (s != null) {
194: try {
195: s.close();
196: } catch (Exception e) {
197: e.printStackTrace();
198: }
199: }
200: if (con != null) {
201: try {
202: con.close();
203: } catch (Exception e) {
204: }
205: }
206: }
207: return workflows;
208: }
209:
210: public static HashMap getWorkflowsByName(String name)
211: throws XflowException {
212:
213: HashMap workflows = new HashMap();
214: Connection con = null;
215: Statement s = null;
216: try {
217: con = Persistence.getConnection();
218: s = con.createStatement();
219:
220: String sql = "select w.workflowId from workflow w, graph g where w.gid = g.gid and g.name = '"
221: + name + "'";
222: log.info(sql);
223: ResultSet rs = s.executeQuery(sql);
224: while (rs.next()) {
225: int wfId = rs.getInt("workflowId");
226: WorkflowId workflowId = new WorkflowId(wfId);
227: Integer key = new Integer(workflowId.getValue());
228: workflows.put(key, workflowId);
229: }
230: } catch (Exception e) {
231: e.printStackTrace();
232: throw new XflowException(
233: "Failed to get workflows from database");
234: } finally {
235: if (s != null) {
236: try {
237: s.close();
238: } catch (Exception e) {
239: e.printStackTrace();
240: }
241: }
242: if (con != null) {
243: try {
244: con.close();
245: } catch (Exception e) {
246: }
247: }
248: }
249: return workflows;
250: }
251:
252: public static Vector getModels() throws XflowException {
253:
254: Vector models = new Vector();
255: Connection con = null;
256: Statement s = null;
257: try {
258: con = Persistence.getConnection();
259: s = con.createStatement();
260:
261: String sql = "select * from graph order by name";
262: log.info(sql);
263: ResultSet rs = s.executeQuery(sql);
264: while (rs.next()) {
265: String name = rs.getString("name");
266: String desc = rs.getString("description");
267: int version = rs.getInt("version");
268: WorkflowModel m = new WorkflowModel();
269: m.name = name;
270: m.version = version;
271: m.description = desc;
272: models.addElement(m);
273: }
274: } catch (Exception e) {
275: e.printStackTrace();
276: throw new XflowException(
277: "Failed to get workflows from database");
278: } finally {
279: if (s != null) {
280: try {
281: s.close();
282: } catch (Exception e) {
283: e.printStackTrace();
284: }
285: }
286: if (con != null) {
287: try {
288: con.close();
289: } catch (Exception e) {
290: }
291: }
292: }
293: return models;
294: }
295:
296: public static void abortWorkflow(WorkflowId workflowId)
297: throws XflowException {
298:
299: int wfId = workflowId.getValue();
300: Connection con = null;
301: Statement s = null;
302: try {
303: con = Persistence.getConnection();
304: s = con.createStatement();
305:
306: String timeEnded = DateUtil.getTimestamp();
307: String sql = "update workflow set isActive = false, timeEnded = '"
308: + timeEnded
309: + "', status = 'ABORTED' where workflowid = "
310: + wfId;
311: log.info(sql);
312: s.execute(sql);
313: } catch (Exception e) {
314: e.printStackTrace();
315: throw new XflowException(
316: "Failed to abort workflow in database");
317: } finally {
318: if (s != null) {
319: try {
320: s.close();
321: } catch (Exception e) {
322: e.printStackTrace();
323: }
324: }
325: if (con != null) {
326: try {
327: con.close();
328: } catch (Exception e) {
329: }
330: }
331: }
332: }
333:
334: public static void suspendWorkflow(WorkflowId workflowId)
335: throws XflowException {
336:
337: int wfId = workflowId.getValue();
338: Connection con = null;
339: Statement s = null;
340: try {
341: con = Persistence.getConnection();
342: s = con.createStatement();
343: String sql = "update workflow set status = 'SUSPENDED' where workflowid = "
344: + wfId;
345: log.info(sql);
346: s.execute(sql);
347: } catch (Exception e) {
348: e.printStackTrace();
349: throw new XflowException(
350: "Failed to suspend workflow in database");
351: } finally {
352: if (s != null) {
353: try {
354: s.close();
355: } catch (Exception e) {
356: e.printStackTrace();
357: }
358: }
359: if (con != null) {
360: try {
361: con.close();
362: } catch (Exception e) {
363: }
364: }
365: }
366: }
367:
368: public static void resumeWorkflow(WorkflowId workflowId)
369: throws XflowException {
370:
371: int wfId = workflowId.getValue();
372: Connection con = null;
373: Statement s = null;
374: try {
375: con = Persistence.getConnection();
376: s = con.createStatement();
377: String sql = "update workflow set status = 'RUNNING' where workflowid = "
378: + wfId;
379: log.info(sql);
380: s.execute(sql);
381: } catch (Exception e) {
382: e.printStackTrace();
383: throw new XflowException(
384: "Failed to resume workflow in database");
385: } finally {
386: if (s != null) {
387: try {
388: s.close();
389: } catch (Exception e) {
390: e.printStackTrace();
391: }
392: }
393: if (con != null) {
394: try {
395: con.close();
396: } catch (Exception e) {
397: }
398: }
399: }
400: }
401:
402: public static WorkflowState getWorkflowState(WorkflowId workflowId)
403: throws XflowException {
404:
405: int wfId = workflowId.getValue();
406: WorkflowState state = null;
407: Connection con = null;
408: Statement s = null;
409: try {
410: con = Persistence.getConnection();
411: s = con.createStatement();
412:
413: String sql = "select * from workflow w, graph g where w.workflowId = "
414: + wfId + " and w.gid = g.gid";
415: log.info(sql);
416: ResultSet rs = s.executeQuery(sql);
417: if (rs.next()) {
418: state = new WorkflowState();
419: String wfName = rs.getString("name");
420: int version = rs.getInt("version");
421: boolean active = rs.getBoolean("isActive");
422: String initiator = rs.getString("initiator");
423: String startTime = rs.getString("timeStarted");
424: java.util.Date stime = DateUtil.parse(startTime);
425: state.timeStarted = stime;
426: if (!active) {
427: String endTime = rs.getString("timeEnded");
428: java.util.Date etime = DateUtil.parse(endTime);
429: state.timeEnded = etime;
430: }
431: state.workflowId = new WorkflowId(wfId);
432: state.workflowName = wfName;
433: state.version = version;
434: state.isActive = active;
435: state.initiator = initiator;
436: state.state = rs.getString("status");
437: if (state.state == null || state.state.equals("")) {
438: if (state.isActive) {
439: state.state = "RUNNING";
440: } else {
441: state.state = "COMPLETED";
442: }
443: }
444:
445: // Load the active processes
446: String sql2 = "select * from inbox where workflowid = "
447: + wfId;
448: log.info(sql2);
449: ResultSet rs2 = s.executeQuery(sql2);
450: while (rs2.next()) {
451: ProcessState ps = new ProcessState();
452: ps.workflowId = new WorkflowId(wfId);
453: ps.processName = rs2.getString("procName");
454: startTime = rs2.getString("timeStarted");
455: stime = DateUtil.parse(startTime);
456: ps.timeStarted = stime;
457: ps.workItemId = new WorkItemId(rs2
458: .getInt("workitemId"));
459: state.activeProcesses.addElement(ps);
460: }
461:
462: // Load the workflow variables
463: String sql3 = "select name, value from workflowvars where workflowid = "
464: + wfId;
465: log.info(sql3);
466: ResultSet rs3 = s.executeQuery(sql3);
467: while (rs3.next()) {
468: String name = rs3.getString("name");
469: String vstr = rs3.getString("value");
470: Object value = HexUtil.hexDecodeObject(vstr);
471: state.variables.put(name, value);
472: }
473: }
474: } catch (Exception e) {
475: e.printStackTrace();
476: throw new XflowException(
477: "Failed to save workflow in database");
478: } finally {
479: if (s != null) {
480: try {
481: s.close();
482: } catch (Exception e) {
483: e.printStackTrace();
484: }
485: }
486: if (con != null) {
487: try {
488: con.close();
489: } catch (Exception e) {
490: }
491: }
492: }
493: return state;
494: }
495:
496: public static void setVariable(int workflowId, String name,
497: Object value) throws XflowException {
498:
499: Connection con = null;
500: Statement s = null;
501: try {
502: System.out.println("Hex Encoding: " + value);
503: String valueStr = HexUtil.hexEncodeObject(value);
504: System.out.println("String to be stored: " + valueStr);
505:
506: con = Persistence.getConnection();
507: s = con.createStatement();
508: String sql = "select * from workflowvars where workflowId = "
509: + workflowId + " and name = '" + name + "'";
510: log.info(sql);
511: ResultSet rs = s.executeQuery(sql);
512: // This is an update of a var
513: if (rs.next()) {
514: sql = "update workflowvars set value = '" + valueStr
515: + "' where workflowId = " + workflowId
516: + " and name = '" + name + "'";
517: } else {
518: sql = "insert into workflowvars values (" + workflowId
519: + ",'" + name + "','" + valueStr + "')";
520: }
521: log.info(sql);
522: s.execute(sql);
523: } catch (Exception e) {
524: e.printStackTrace();
525: throw new XflowException(
526: "Failed to set workflow variable in database");
527: } finally {
528: if (s != null) {
529: try {
530: s.close();
531: } catch (Exception e) {
532: e.printStackTrace();
533: }
534: }
535: if (con != null) {
536: try {
537: con.close();
538: } catch (Exception e) {
539: }
540: }
541: }
542: }
543:
544: public static Object getVariable(int workflowId, String name)
545: throws XflowException {
546:
547: Object result = null;
548: Connection con = null;
549: Statement s = null;
550: try {
551: con = Persistence.getConnection();
552: s = con.createStatement();
553:
554: String sql = "select * from workflowvars where workflowId = "
555: + workflowId + " and name = '" + name + "'";
556: log.info(sql);
557: ResultSet rs = s.executeQuery(sql);
558: if (rs.next()) {
559: String vstr = rs.getString("value");
560: System.out.println("Stored String: " + vstr);
561: result = HexUtil.hexDecodeObject(vstr);
562: }
563: } catch (Exception e) {
564: e.printStackTrace();
565: throw new XflowException(
566: "Failed to get workflow variable from database");
567: } finally {
568: if (s != null) {
569: try {
570: s.close();
571: } catch (Exception e) {
572: e.printStackTrace();
573: }
574: }
575: if (con != null) {
576: try {
577: con.close();
578: } catch (Exception e) {
579: }
580: }
581: }
582: return result;
583: }
584:
585: public static void setCompleted(int workflowId)
586: throws XflowException {
587:
588: Connection con = null;
589: Statement s = null;
590: try {
591: con = Persistence.getConnection();
592: s = con.createStatement();
593: String timeEnded = DateUtil.getTimestamp();
594: String sql = "update workflow set isActive = 'false', timeEnded = '"
595: + timeEnded
596: + "', status = 'COMPLETED' where workflowId = "
597: + workflowId;
598: log.info(sql);
599: s.execute(sql);
600:
601: // Do house cleaning of workflow vars, workitems? We'll keep them in the db
602: // until we develop a data warehousing solution.
603:
604: } catch (Exception e) {
605: e.printStackTrace();
606: throw new XflowException(
607: "Failed to set workflow completion time in database.");
608: } finally {
609: if (s != null) {
610: try {
611: s.close();
612: } catch (Exception e) {
613: e.printStackTrace();
614: }
615: }
616: if (con != null) {
617: try {
618: con.close();
619: } catch (Exception e) {
620: }
621: }
622: }
623: }
624:
625: public static Vector getProcessesWithTimeouts()
626: throws XflowException {
627:
628: Vector v = new Vector();
629: Connection con = null;
630: Statement s = null;
631: try {
632: con = Persistence.getConnection();
633: s = con.createStatement();
634: String pName = null;
635: int pId = -1;
636: int pTout = -1;
637: String pThdl = null;
638:
639: String sql = "select n.nid, n.name, p.value from node n, nodeprops p where "
640: + " n.nid = p.nid and p.name = 'timeoutMinutes'";
641: //log.info (sql);
642: ResultSet rs = s.executeQuery(sql);
643: while (rs.next()) {
644: pName = rs.getString("name");
645: pId = rs.getInt("nid");
646: String vstr = rs.getString("value");
647: Object value = HexUtil.hexDecodeObject(vstr);
648: Integer iValue = (Integer) value;
649: pTout = iValue.intValue();
650:
651: sql = "select p.value from node n, nodeprops p where n.nid = p.nid and n.nid = "
652: + pId + " and p.name = 'timeoutHandler'";
653: //log.info (sql);
654: ResultSet rs2 = s.executeQuery(sql);
655: if (rs2.next()) {
656: vstr = rs2.getString("value");
657: value = HexUtil.hexDecodeObject(vstr);
658: pThdl = (String) value;
659: }
660:
661: sql = "select w.workflowId from workflow w, graph g, node n where w.gid = g.gid and g.gid = n.gid and n.nid = "
662: + pId;
663: //log.info (sql);
664: ResultSet rs3 = s.executeQuery(sql);
665: while (rs3.next()) {
666: int wfId = rs3.getInt("workflowId");
667: ProcessWithTimeout pto = new ProcessWithTimeout();
668: pto.workflowId = wfId;
669: pto.processName = pName;
670: pto.timeoutMinutes = pTout;
671: pto.timeoutHandler = pThdl;
672: v.addElement(pto);
673: }
674: }
675: } catch (Exception e) {
676: e.printStackTrace();
677: throw new XflowException(
678: "Failed to set workflow completion time in database.");
679: } finally {
680: if (s != null) {
681: try {
682: s.close();
683: } catch (Exception e) {
684: e.printStackTrace();
685: }
686: }
687: if (con != null) {
688: try {
689: con.close();
690: } catch (Exception e) {
691: }
692: }
693: }
694: return v;
695: }
696: }
|