001: /*
002: * argun 1.0
003: * Web 2.0 delivery framework
004: * Copyright (C) 2007 Hammurapi Group
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://www.hammurapi.biz
021: * e-Mail: support@hammurapi.biz
022: */
023: package biz.hammurapi.web.process;
024:
025: import java.io.ByteArrayOutputStream;
026: import java.io.IOException;
027: import java.io.ObjectInputStream;
028: import java.io.ObjectOutputStream;
029: import java.sql.Connection;
030: import java.sql.Date;
031: import java.sql.SQLException;
032: import java.util.ArrayList;
033: import java.util.Collection;
034: import java.util.HashMap;
035: import java.util.Iterator;
036: import java.util.Map;
037: import java.util.zip.GZIPInputStream;
038:
039: import javax.servlet.ServletInputStream;
040: import javax.servlet.ServletOutputStream;
041: import javax.servlet.http.HttpServletRequest;
042: import javax.servlet.http.HttpServletResponse;
043:
044: import org.apache.log4j.Logger;
045:
046: import biz.hammurapi.config.ConfigurationException;
047: import biz.hammurapi.sql.IDatabaseObject;
048: import biz.hammurapi.sql.IdentityGenerator;
049: import biz.hammurapi.sql.IdentityManager;
050: import biz.hammurapi.sql.IdentityRetriever;
051: import biz.hammurapi.sql.SQLProcessor;
052: import biz.hammurapi.sql.Transaction;
053: import biz.hammurapi.util.Attributable;
054: import biz.hammurapi.web.ActionsBase;
055: import biz.hammurapi.web.HttpError;
056: import biz.hammurapi.web.menu.MenuActions;
057: import biz.hammurapi.web.menu.sql.MenuEngine;
058: import biz.hammurapi.web.process.sql.Process;
059: import biz.hammurapi.web.process.sql.ProcessEngine;
060: import biz.hammurapi.web.process.sql.ProcessImpl;
061: import biz.hammurapi.web.process.sql.ProcessTask;
062: import biz.hammurapi.web.process.sql.ProcessTaskArtifact;
063: import biz.hammurapi.web.process.sql.ProcessTaskImpl;
064: import biz.hammurapi.web.process.sql.ProcessTransitionImpl;
065:
066: public class ProcessActions extends ActionsBase {
067: private static final Logger logger = Logger
068: .getLogger(ProcessActions.class);
069:
070: protected static ProcessEngine getEngine(HttpServletRequest request) {
071: return new ProcessEngine((SQLProcessor) getGlobal(request,
072: "sql-processor"));
073: }
074:
075: /**
076: * Stores process in the database.
077: * @param request
078: * @param response
079: */
080: public void save(HttpServletRequest request,
081: HttpServletResponse response) throws IOException {
082: try {
083: ServletInputStream in = request.getInputStream();
084: GZIPInputStream gzis = new GZIPInputStream(in);
085: ObjectInputStream ois = new ObjectInputStream(gzis);
086: biz.hammurapi.web.process.sql.Process data = (biz.hammurapi.web.process.sql.Process) ois
087: .readObject();
088: Transaction transaction = Boolean.TRUE
089: .equals(((Attributable) data).getAttribute("new")) ? create(
090: data, request)
091: : update(data, request);
092: SQLProcessor processor = (SQLProcessor) getGlobal(request,
093: "sql-processor");
094: processor.executeTransaction(transaction);
095: ois.close();
096: gzis.close();
097: in.close();
098: } catch (Exception e) {
099: logger.error("Could not create process", e);
100: response.sendError(500, e.toString());
101: }
102: }
103:
104: private Transaction update(
105: final biz.hammurapi.web.process.sql.Process data,
106: final HttpServletRequest request) {
107: return new Transaction() {
108:
109: public boolean execute(SQLProcessor processor)
110: throws SQLException {
111: Connection con = processor.getConnection();
112: ProcessEngine engine = new ProcessEngine(
113: new SQLProcessor(con, null));
114: data.setLastModified(new Date(System
115: .currentTimeMillis()));
116: data.setVersion(data.getVersion() + 1);
117: engine.deleteProcessTaskByProcess(data.getId());
118: engine.updateProcess(data);
119: insertTasksAndTransitions(data,
120: (IdentityManager) getGlobal(request,
121: "db/IdentityManager"), con, engine);
122: processor.releaseConnection(con);
123: return true;
124: }
125:
126: };
127: }
128:
129: private Transaction create(
130: final biz.hammurapi.web.process.sql.Process data,
131: final HttpServletRequest request) {
132: return new Transaction() {
133:
134: public boolean execute(SQLProcessor processor)
135: throws SQLException {
136: IdentityManager identityManager = (IdentityManager) getGlobal(
137: request, "db/IdentityManager");
138: Connection con = processor.getConnection();
139: ProcessEngine engine = new ProcessEngine(
140: new SQLProcessor(con, null));
141: data.setLastModified(new Date(System
142: .currentTimeMillis()));
143: data.setVersion(1);
144: // User user = (User) request.getSession().getAttribute(AuthFilter.USER);
145: // data.setOwner(user==null ? null : user.getLoginName());
146: String menuId = request.getParameter("MENU_ID");
147: if (!isBlank(menuId)) {
148: data.setOwnerMenu(Integer.parseInt(menuId));
149: }
150: if (identityManager instanceof IdentityGenerator) {
151: data.setId(((IdentityGenerator) identityManager)
152: .generate(con, "PROCESS_TASK_DEF"));
153: }
154: engine.insertProcess(data);
155: if (identityManager instanceof IdentityRetriever) {
156: data.setId(((IdentityRetriever) identityManager)
157: .retrieve(con));
158: }
159:
160: insertTasksAndTransitions(data, identityManager, con,
161: engine);
162:
163: processor.releaseConnection(con);
164: return true;
165: }
166:
167: };
168: }
169:
170: private void insertTasksAndTransitions(
171: final biz.hammurapi.web.process.sql.Process data,
172: IdentityManager identityManager, Connection con,
173: ProcessEngine engine) throws SQLException {
174: Collection tasks = (Collection) ((Attributable) data)
175: .getAttribute("tasks");
176: if (tasks != null) {
177: Iterator it = tasks.iterator();
178: while (it.hasNext()) {
179: ProcessTaskImpl originalTask = (ProcessTaskImpl) it
180: .next();
181: class PtdiEx extends ProcessTaskImpl {
182: PtdiEx() {
183: super (true);
184: }
185:
186: void crearId() {
187: getColumn("ID").clear();
188: }
189: }
190:
191: PtdiEx task = new PtdiEx();
192: task.copy(originalTask);
193: task.crearId();
194:
195: task.setProcessId(data.getId());
196: if (identityManager instanceof IdentityGenerator) {
197: task.setId(((IdentityGenerator) identityManager)
198: .generate(con, "PROCESS_TASK_DEF"));
199: }
200: engine.insertProcessTask(task);
201: if (identityManager instanceof IdentityRetriever) {
202: task.setId(((IdentityRetriever) identityManager)
203: .retrieve(con));
204: }
205: originalTask.setId(task.getId()); // To propagate to transition.
206:
207: Collection taskArtifacts = (Collection) originalTask
208: .getAttribute("artifacts");
209: if (taskArtifacts != null) {
210: Iterator ait = taskArtifacts.iterator();
211: while (ait.hasNext()) {
212: ProcessTaskArtifact pat = (ProcessTaskArtifact) ait
213: .next();
214: engine
215: .insertProcessTaskArtifact(
216: task.getId(), pat
217: .getArtifactId(), pat
218: .getInputMode(), pat
219: .getOutputMode());
220: }
221: }
222: }
223: }
224:
225: Collection transitions = (Collection) ((Attributable) data)
226: .getAttribute("transitions");
227: if (transitions != null) {
228: Iterator it = transitions.iterator();
229: while (it.hasNext()) {
230: ProcessTransitionImpl originalTransition = (ProcessTransitionImpl) it
231: .next();
232:
233: class PTEx extends ProcessTransitionImpl {
234: PTEx() {
235: super (true);
236: }
237:
238: void crearId() {
239: getColumn("ID").clear();
240: }
241: }
242:
243: PTEx transition = new PTEx();
244: transition.copy(originalTransition);
245: transition.crearId();
246:
247: ProcessTask transitionSource = (ProcessTask) ((IDatabaseObject) originalTransition)
248: .getColumnAttribute("FROM_TASK", "task");
249: transition.setFromTask(transitionSource.getId());
250: ProcessTask transitionTarget = (ProcessTask) ((IDatabaseObject) originalTransition)
251: .getColumnAttribute("TO_TASK", "task");
252: transition.setToTask(transitionTarget.getId());
253: engine.insertProcessTransition(transition);
254: }
255: }
256: }
257:
258: public void get(HttpServletRequest request,
259: HttpServletResponse response) throws IOException {
260: try {
261: ProcessEngine engine = getEngine(request);
262: ProcessImpl process = (ProcessImpl) engine
263: .getProcess(Integer.parseInt(request
264: .getParameter("ID")));
265: if (process == null) {
266: response.sendError(404, "Invalid process id");
267: return;
268: }
269:
270: process.setProcessImage(null); // No need to transfer image over the wire.
271: Collection tasks = engine.getProcessTaskByProcess(process
272: .getId(), new ArrayList());
273: Iterator it = tasks.iterator();
274: while (it.hasNext()) {
275: ProcessTaskImpl pti = (ProcessTaskImpl) it.next();
276: pti.setAttribute("artifacts", engine
277: .getProcessTaskArtifactByTask(pti.getId(),
278: new ArrayList()));
279: }
280:
281: process.setAttribute("tasks", tasks);
282: Collection transitions = engine.getProcessTransitions(
283: process.getId(), process.getId(), new ArrayList());
284: process.setAttribute("transitions", transitions);
285: it = transitions.iterator();
286: while (it.hasNext()) {
287: ProcessTransitionImpl transition = (ProcessTransitionImpl) it
288: .next();
289: Iterator tit = tasks.iterator();
290: while (tit.hasNext()) {
291: ProcessTaskImpl task = (ProcessTaskImpl) tit.next();
292: if (transition.getFromTask() == task.getId()) {
293: transition.setColumnAttribute("FROM_TASK",
294: "task", task);
295: }
296: if (transition.getToTask() == task.getId()) {
297: transition.setColumnAttribute("TO_TASK",
298: "task", task);
299: }
300: }
301: }
302: ByteArrayOutputStream baos = new ByteArrayOutputStream();
303: //GZIPOutputStream gzos = new GZIPOutputStream(baos);
304: ObjectOutputStream oos = new ObjectOutputStream(baos /* gzos */);
305: oos.writeObject(process);
306: oos.close();
307: //gzos.close();
308: baos.close();
309: byte[] bytes = baos.toByteArray();
310: response.setContentType("application/binary");
311: response.setContentLength(bytes.length);
312: //System.out.println("Content length:"+bytes.length);
313: ServletOutputStream out = response.getOutputStream();
314: out.write(bytes);
315: out.close();
316: } catch (Exception e) {
317: logger.error(
318: "Could not retrieve process from the database", e);
319: response.sendError(500, e.toString());
320: }
321: }
322:
323: /**
324: * Retrieves process with tasks and transitions to be XML-ized and rendered for viewing
325: * @param request
326: * @param response
327: * @return
328: * @throws SQLException
329: * @throws NumberFormatException
330: * @throws SQLException
331: * @throws NumberFormatException
332: */
333: public Object getXml(HttpServletRequest request,
334: HttpServletResponse response) throws NumberFormatException,
335: SQLException {
336: ProcessEngine engine = getEngine(request);
337: ProcessImpl ret = (ProcessImpl) engine.getProcess(Integer
338: .parseInt(request.getParameter("ID")));
339: if (ret == null) {
340: return new HttpError(404, "Invalid process id");
341: }
342: ret.setProcessImage(null); // No need to transfer image over the wire.
343: Collection tasks = engine.getProcessTaskByProcess(ret.getId(),
344: new ArrayList());
345: ret.setAttribute("tasks", tasks);
346: Collection transitions = engine.getProcessTransitions(ret
347: .getId(), ret.getId(), new ArrayList());
348: ret.setAttribute("transitions", transitions);
349: return ret;
350: }
351:
352: public void getImage(HttpServletRequest request,
353: HttpServletResponse response) throws NumberFormatException,
354: SQLException, IOException {
355: biz.hammurapi.web.process.sql.Process process = getEngine(
356: request).getProcess(
357: Integer.parseInt(request.getParameter("ID")));
358: if (process == null) {
359: response.sendError(404, "Invalid process id");
360: } else {
361: byte[] content = process.getProcessImage();
362: if (content == null) {
363: response.sendError(404, "Process image not found");
364: } else {
365: response.setContentType(process.getImageType());
366: response.setContentLength(content.length);
367: ServletOutputStream out = response.getOutputStream();
368: out.write(content);
369: out.close();
370: }
371: }
372: }
373:
374: /**
375: * Returns list of menus with processes for AJAX tree.
376: * @param request
377: * @param response
378: * @param servlet
379: * @return
380: * @throws SQLException
381: * @throws
382: * @throws SQLException
383: * @throws ConfigurationException
384: */
385: public Object getMenu(HttpServletRequest request,
386: HttpServletResponse response) throws SQLException {
387: String parent = request.getParameter("parentId");
388: MenuEngine engine = MenuActions.getEngine(request);
389: Map ret = new HashMap();
390: if (parent == null) {
391: String targetForm = request.getParameter("targetForm");
392: if (targetForm != null) {
393: ret.put("targetForm", targetForm);
394: }
395:
396: String targetField = request.getParameter("targetField");
397: if (targetField != null) {
398: ret.put("targetField", targetField);
399: }
400:
401: ret.put("items", engine.getRootMenus(new ArrayList()));
402: } else {
403: int parentInt = Integer.parseInt(parent);
404: ret.put("items", engine.getMenuWithChildCount(parentInt,
405: new ArrayList()));
406: ret.put("processes", getEngine(request).getProcessByOwner(
407: parentInt, new ArrayList()));
408: ret.put("path", MenuActions.path(parent, engine));
409: }
410: return ret;
411: }
412:
413: /**
414: * Menu/interaction path
415: * @param request
416: * @param response
417: * @param servlet
418: * @return
419: * @throws NumberFormatException
420: * @throws SQLException
421: */
422: public String path(HttpServletRequest request,
423: HttpServletResponse response) throws NumberFormatException,
424: SQLException {
425: String idStr = request.getParameter("id");
426: if (idStr == null) {
427: return "Id parameter is missing";
428: }
429:
430: if ("null".equals(idStr)) {
431: return "(none)";
432: }
433:
434: MenuEngine engine = MenuActions.getEngine(request);
435:
436: int processId = Integer.parseInt(idStr);
437: Process process = getEngine(request).getProcess(processId);
438: if (process == null) {
439: return "Invalid process ID";
440: }
441:
442: return MenuActions.path(String.valueOf(process.getOwnerMenu()),
443: engine)
444: + " : " + process.getName();
445: }
446: }
|