0001: /*
0002: * argun 1.0
0003: * Web 2.0 delivery framework
0004: * Copyright (C) 2007 Hammurapi Group
0005: *
0006: * This program is free software; you can redistribute it and/or
0007: * modify it under the terms of the GNU Lesser General Public
0008: * License as published by the Free Software Foundation; either
0009: * version 2 of the License, or (at your option) any later version.
0010: *
0011: * This program is distributed in the hope that it will be useful,
0012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014: * Lesser General Public License for more details.
0015: *
0016: * You should have received a copy of the GNU Lesser General Public
0017: * License along with this library; if not, write to the Free Software
0018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0019: *
0020: * URL: http://www.hammurapi.biz
0021: * e-Mail: support@hammurapi.biz
0022: */
0023: package biz.hammurapi.web.interaction;
0024:
0025: import java.io.ByteArrayOutputStream;
0026: import java.io.IOException;
0027: import java.io.InputStreamReader;
0028: import java.io.ObjectInputStream;
0029: import java.io.ObjectOutputStream;
0030: import java.io.Reader;
0031: import java.io.StringWriter;
0032: import java.sql.Connection;
0033: import java.sql.Date;
0034: import java.sql.SQLException;
0035: import java.util.ArrayList;
0036: import java.util.Collection;
0037: import java.util.Enumeration;
0038: import java.util.HashMap;
0039: import java.util.HashSet;
0040: import java.util.Iterator;
0041: import java.util.Map;
0042: import java.util.Set;
0043: import java.util.zip.GZIPInputStream;
0044:
0045: import javax.servlet.ServletInputStream;
0046: import javax.servlet.ServletOutputStream;
0047: import javax.servlet.http.HttpServletRequest;
0048: import javax.servlet.http.HttpServletResponse;
0049: import javax.servlet.http.HttpSession;
0050:
0051: import org.apache.log4j.Logger;
0052:
0053: import biz.hammurapi.config.ConfigurationException;
0054: import biz.hammurapi.config.Context;
0055: import biz.hammurapi.config.PropertyParser;
0056: import biz.hammurapi.sql.IDatabaseObject;
0057: import biz.hammurapi.sql.IdentityGenerator;
0058: import biz.hammurapi.sql.IdentityManager;
0059: import biz.hammurapi.sql.IdentityRetriever;
0060: import biz.hammurapi.sql.SQLExceptionEx;
0061: import biz.hammurapi.sql.SQLProcessor;
0062: import biz.hammurapi.sql.Transaction;
0063: import biz.hammurapi.util.Attributable;
0064: import biz.hammurapi.web.ActionsBase;
0065: import biz.hammurapi.web.HammurapiWebException;
0066: import biz.hammurapi.web.HttpError;
0067: import biz.hammurapi.web.RequestContext;
0068: import biz.hammurapi.web.SimpleRedirect;
0069: import biz.hammurapi.web.interaction.DynaBind.InteractionBind;
0070: import biz.hammurapi.web.interaction.DynaBind.MenuBind;
0071: import biz.hammurapi.web.interaction.DynaBind.UrlBind;
0072: import biz.hammurapi.web.interaction.InteractionFactory.InteractionDefinition.StepDefinition;
0073: import biz.hammurapi.web.interaction.InteractionInstance.StepInstance;
0074: import biz.hammurapi.web.interaction.sql.Interaction;
0075: import biz.hammurapi.web.interaction.sql.InteractionEngine;
0076: import biz.hammurapi.web.interaction.sql.InteractionImpl;
0077: import biz.hammurapi.web.interaction.sql.InteractionStep;
0078: import biz.hammurapi.web.interaction.sql.InteractionStepImpl;
0079: import biz.hammurapi.web.interaction.sql.InteractionTransitionImpl;
0080: import biz.hammurapi.web.menu.Menu;
0081: import biz.hammurapi.web.menu.MenuActions;
0082: import biz.hammurapi.web.menu.MenuFilter;
0083: import biz.hammurapi.web.menu.sql.HelpTopic;
0084: import biz.hammurapi.web.menu.sql.HelpTopicImpl;
0085: import biz.hammurapi.web.menu.sql.MenuEngine;
0086: import biz.hammurapi.web.menu.sql.XmenuImpl;
0087: import biz.hammurapi.web.properties.PropertySet;
0088: import biz.hammurapi.web.security.AuthFilter;
0089: import biz.hammurapi.web.security.User;
0090: import biz.hammurapi.web.util.GuidGenerator;
0091:
0092: public class InterActions extends ActionsBase {
0093: static final String CREATE_ID = "create-id";
0094: private static final String BIND_TYPE_PREFIX = "BIND_TYPE_";
0095: private static final String INTERACTION_PREFIX = "interaction_";
0096: private static final String NEXT_STEP_URI = "/system/interaction.InterActions/next?interaction=";
0097: private static final Logger logger = Logger
0098: .getLogger(InterActions.class);
0099:
0100: protected static InteractionEngine getEngine(
0101: HttpServletRequest request) {
0102: return new InteractionEngine((SQLProcessor) getGlobal(request,
0103: "sql-processor"));
0104: }
0105:
0106: /**
0107: * Stores interaction in the database.
0108: * @param request
0109: * @param response
0110: */
0111: public void save(HttpServletRequest request,
0112: HttpServletResponse response) throws IOException {
0113: try {
0114: ServletInputStream in = request.getInputStream();
0115: GZIPInputStream gzis = new GZIPInputStream(in);
0116: ObjectInputStream ois = new ObjectInputStream(gzis);
0117: biz.hammurapi.web.interaction.sql.Interaction data = (biz.hammurapi.web.interaction.sql.Interaction) ois
0118: .readObject();
0119:
0120: Transaction transaction = null;
0121: if (Boolean.TRUE.equals(((Attributable) data)
0122: .getAttribute("new"))) {
0123: Object createId = ((Attributable) data)
0124: .getAttribute(CREATE_ID);
0125: if (createId != null) {
0126: synchronized (createMap) {
0127: Integer id = (Integer) createMap.get(createId);
0128: if (id != null) {
0129: data.setId(id.intValue());
0130: transaction = update(data, request);
0131: }
0132: }
0133: }
0134:
0135: if (transaction == null) {
0136: transaction = create(data, request);
0137: }
0138: } else {
0139: transaction = update(data, request);
0140: }
0141:
0142: SQLProcessor processor = (SQLProcessor) getGlobal(request,
0143: "sql-processor");
0144: processor.executeTransaction(transaction);
0145: ois.close();
0146: gzis.close();
0147: in.close();
0148:
0149: InteractionFactory factory = (InteractionFactory) getGlobal(
0150: request, "db/InteractionFactory");
0151: if (factory != null) {
0152: factory.invalidateInteractions();
0153: }
0154: } catch (Exception e) {
0155: logger.error("Could not create/update interaction", e);
0156: response.sendError(500, e.toString());
0157: }
0158: }
0159:
0160: private Transaction update(final Interaction data,
0161: final HttpServletRequest request) {
0162: return new Transaction() {
0163:
0164: public boolean execute(SQLProcessor processor)
0165: throws SQLException {
0166: Connection con = processor.getConnection();
0167: InteractionEngine engine = new InteractionEngine(
0168: new SQLProcessor(con, null));
0169: data.setLastModified(new Date(System
0170: .currentTimeMillis()));
0171: data.setVersion(data.getVersion() + 1);
0172: engine.deleteInteractionStepByInteraction(data.getId());
0173:
0174: GuidGenerator guidGenerator = (GuidGenerator) getGlobal(
0175: request, "db/guid-generator");
0176: if (guidGenerator != null && isBlank(data.getGuid())) {
0177: try {
0178: data.setGuid(guidGenerator.nextGUID());
0179: } catch (HammurapiWebException e) {
0180: throw new SQLExceptionEx(e);
0181: }
0182: }
0183:
0184: engine.updateInteraction(data);
0185: insertStepsAndTransitions(data,
0186: (IdentityManager) getGlobal(request,
0187: "db/IdentityManager"), con, engine);
0188: processor.releaseConnection(con);
0189: return true;
0190: }
0191:
0192: };
0193: }
0194:
0195: private Map createMap = new HashMap();
0196:
0197: private Transaction create(final Interaction data,
0198: final HttpServletRequest request) {
0199: return new Transaction() {
0200:
0201: public boolean execute(SQLProcessor processor)
0202: throws SQLException {
0203: IdentityManager identityManager = (IdentityManager) getGlobal(
0204: request, "db/IdentityManager");
0205: Connection con = processor.getConnection();
0206: InteractionEngine engine = new InteractionEngine(
0207: new SQLProcessor(con, null));
0208: data.setLastModified(new Date(System
0209: .currentTimeMillis()));
0210: data.setVersion(1);
0211: data.setOwnerMenu(Integer.parseInt(request
0212: .getParameter("MENU_ID")));
0213: if (identityManager instanceof IdentityGenerator) {
0214: data.setId(((IdentityGenerator) identityManager)
0215: .generate(con, "INTERACTION"));
0216: }
0217:
0218: GuidGenerator guidGenerator = (GuidGenerator) getGlobal(
0219: request, "db/guid-generator");
0220: if (guidGenerator != null && isBlank(data.getGuid())) {
0221: try {
0222: data.setGuid(guidGenerator.nextGUID());
0223: } catch (HammurapiWebException e) {
0224: throw new SQLExceptionEx(e);
0225: }
0226: }
0227:
0228: engine.insertInteraction(data);
0229: if (identityManager instanceof IdentityRetriever) {
0230: data.setId(((IdentityRetriever) identityManager)
0231: .retrieve(con));
0232: }
0233:
0234: insertStepsAndTransitions(data, identityManager, con,
0235: engine);
0236:
0237: processor.releaseConnection(con);
0238:
0239: Object createId = ((Attributable) data)
0240: .getAttribute(CREATE_ID);
0241: if (createId != null) {
0242: synchronized (createMap) {
0243: createMap.put(createId, new Integer(data
0244: .getId()));
0245: }
0246: }
0247: return true;
0248: }
0249:
0250: };
0251: }
0252:
0253: private void insertStepsAndTransitions(final Interaction data,
0254: IdentityManager identityManager, Connection con,
0255: InteractionEngine engine) throws SQLException {
0256: Collection steps = (Collection) ((Attributable) data)
0257: .getAttribute("steps");
0258: if (steps != null) {
0259: Iterator it = steps.iterator();
0260: while (it.hasNext()) {
0261: InteractionStepImpl originalStep = (InteractionStepImpl) it
0262: .next();
0263: class ISEx extends InteractionStepImpl {
0264: ISEx() {
0265: super (true);
0266: }
0267:
0268: void crearId() {
0269: getColumn("ID").clear();
0270: }
0271: }
0272:
0273: ISEx step = new ISEx();
0274: step.copy(originalStep);
0275: step.crearId();
0276:
0277: step.setInteractionId(data.getId());
0278: if (identityManager instanceof IdentityGenerator) {
0279: step.setId(((IdentityGenerator) identityManager)
0280: .generate(con, "INTERACTION_STEP"));
0281: }
0282: engine.insertInteractionStep(step);
0283: if (identityManager instanceof IdentityRetriever) {
0284: step.setId(((IdentityRetriever) identityManager)
0285: .retrieve(con));
0286: }
0287: originalStep.setId(step.getId()); // To propagate to transition.
0288: }
0289: }
0290:
0291: Collection transitions = (Collection) ((Attributable) data)
0292: .getAttribute("transitions");
0293: if (transitions != null) {
0294: Iterator it = transitions.iterator();
0295: while (it.hasNext()) {
0296: InteractionTransitionImpl originalTransition = (InteractionTransitionImpl) it
0297: .next();
0298:
0299: class ITEx extends InteractionTransitionImpl {
0300: ITEx() {
0301: super (true);
0302: }
0303:
0304: void crearId() {
0305: getColumn("ID").clear();
0306: }
0307: }
0308:
0309: ITEx transition = new ITEx();
0310: transition.copy(originalTransition);
0311: transition.crearId();
0312:
0313: InteractionStep transitionSource = (InteractionStep) ((IDatabaseObject) originalTransition)
0314: .getColumnAttribute("FROM_STEP", "step");
0315: transition.setFromStep(transitionSource.getId());
0316: InteractionStep transitionTarget = (InteractionStep) ((IDatabaseObject) originalTransition)
0317: .getColumnAttribute("TO_STEP", "step");
0318: transition.setToStep(transitionTarget.getId());
0319: engine.insertInteractionTransition(transition);
0320: }
0321: }
0322: }
0323:
0324: public void get(HttpServletRequest request,
0325: HttpServletResponse response) throws IOException {
0326: try {
0327: InteractionEngine engine = getEngine(request);
0328: InteractionImpl interaction = (InteractionImpl) engine
0329: .getInteraction(Integer.parseInt(request
0330: .getParameter("ID")));
0331: if (interaction == null) {
0332: response.sendError(404, "Invalid interaction id");
0333: return;
0334: }
0335:
0336: interaction.setInteractionImage(null); // No need to transfer image over the wire.
0337: Collection steps = engine.getInteractionStepByInteraction(
0338: interaction.getId(), new ArrayList());
0339: interaction.setAttribute("steps", steps);
0340: Collection transitions = engine.getInteractionTransitions(
0341: interaction.getId(), interaction.getId(),
0342: new ArrayList());
0343: interaction.setAttribute("transitions", transitions);
0344: Iterator it = transitions.iterator();
0345: while (it.hasNext()) {
0346: InteractionTransitionImpl transition = (InteractionTransitionImpl) it
0347: .next();
0348: Iterator sit = steps.iterator();
0349: while (sit.hasNext()) {
0350: InteractionStepImpl step = (InteractionStepImpl) sit
0351: .next();
0352: if (transition.getFromStep() == step.getId()) {
0353: transition.setColumnAttribute("FROM_STEP",
0354: "step", step);
0355: }
0356: if (transition.getToStep() == step.getId()) {
0357: transition.setColumnAttribute("TO_STEP",
0358: "step", step);
0359: }
0360: }
0361: }
0362: ByteArrayOutputStream baos = new ByteArrayOutputStream();
0363: //GZIPOutputStream gzos = new GZIPOutputStream(baos);
0364: ObjectOutputStream oos = new ObjectOutputStream(baos /* gzos */);
0365: oos.writeObject(interaction);
0366: oos.close();
0367: //gzos.close();
0368: baos.close();
0369: byte[] bytes = baos.toByteArray();
0370: response.setContentType("application/binary");
0371: response.setContentLength(bytes.length);
0372: //System.out.println("Content length:"+bytes.length);
0373: ServletOutputStream out = response.getOutputStream();
0374: out.write(bytes);
0375: out.close();
0376: } catch (Exception e) {
0377: logger.error(
0378: "Could not retrieve interaction from the database",
0379: e);
0380: response.sendError(500, e.toString());
0381: }
0382: }
0383:
0384: /**
0385: * Retrieves interaction with steps and transitions to be XML-ized and rendered for viewing
0386: * @param request
0387: * @param response
0388: * @return
0389: * @throws SQLException
0390: * @throws NumberFormatException
0391: * @throws SQLException
0392: * @throws NumberFormatException
0393: */
0394: public Object getXml(HttpServletRequest request,
0395: HttpServletResponse response) throws NumberFormatException,
0396: SQLException {
0397: InteractionEngine engine = getEngine(request);
0398: String id = request.getParameter("ID");
0399: if (id == null) {
0400: Menu matched = getMatched(request);
0401: id = matched == null ? null : matched
0402: .getMatchParameter("ID");
0403: if (id == null) {
0404: return "ID parameter is missing";
0405: }
0406: }
0407: InteractionImpl ret = (InteractionImpl) engine
0408: .getInteraction(Integer.parseInt(id));
0409: if (ret == null) {
0410: return new HttpError(404, "Invalid interaction id");
0411: }
0412: ret.setColumnAttribute("OWNER_MENU", "path", path(request,
0413: String.valueOf(ret.getOwnerMenu())));
0414: ret.setInteractionImage(null); // No need to transfer image over the wire.
0415: Collection steps = engine.getInteractionStepByInteraction(ret
0416: .getId(), new ArrayList());
0417: Iterator it = steps.iterator();
0418: while (it.hasNext()) {
0419: InteractionStep step = (InteractionStep) it.next();
0420: if ("Menu".equals(step.getBindType())) {
0421: if (step.getBindMenu() == null) {
0422: step.setBindType("Dynamic");
0423: } else {
0424: ((IDatabaseObject) step).setColumnAttribute(
0425: "BIND_MENU", "path", path(request, step
0426: .getBindMenu().toString()));
0427: ((Attributable) step).setAttribute(
0428: "bind-menu-interaction", step.getBindMenu()
0429: .toString());
0430: }
0431: } else if ("Interaction".equals(step.getBindType())) {
0432: if (step.getBindInteraction() == null) {
0433: step.setBindType("Dynamic");
0434: } else {
0435: ((IDatabaseObject) step).setColumnAttribute(
0436: "BIND_INTERACTION", "path",
0437: path(request, INTERACTION_PREFIX
0438: + step.getBindInteraction()));
0439: ((Attributable) step).setAttribute(
0440: "bind-menu-interaction", INTERACTION_PREFIX
0441: + step.getBindInteraction());
0442: }
0443: }
0444: }
0445: ret.setAttribute("steps", steps);
0446: Collection transitions = engine.getInteractionTransitions(ret
0447: .getId(), ret.getId(), new ArrayList());
0448: ret.setAttribute("transitions", transitions);
0449:
0450: String referrer = getReferrer(request);
0451: if (referrer != null) {
0452: ret.setAttribute("referrer", referrer);
0453: }
0454: return ret;
0455: }
0456:
0457: public void getImage(HttpServletRequest request,
0458: HttpServletResponse response) throws NumberFormatException,
0459: SQLException, IOException {
0460: Interaction interaction = getEngine(request).getInteraction(
0461: Integer.parseInt(request.getParameter("ID")));
0462: if (interaction == null) {
0463: response.sendError(404, "Invalid interaction id");
0464: } else {
0465: byte[] content = interaction.getInteractionImage();
0466: if (content == null) {
0467: response.sendError(404, "Interaction image not found");
0468: } else {
0469: response.setContentType(interaction.getImageType());
0470: response.setContentLength(content.length);
0471: ServletOutputStream out = response.getOutputStream();
0472: out.write(content);
0473: out.close();
0474: }
0475: }
0476: }
0477:
0478: /**
0479: * Starts interaction.
0480: * Parameters:
0481: * interaction_id - ID of interaction to start.
0482: * EXIT_URL - URL to redirect to after finishing interaction.
0483: *
0484: * @param request
0485: * @param response
0486: * @throws SQLException
0487: * @throws HammurapiWebException
0488: * @throws
0489: * @throws NumberFormatException
0490: */
0491: public Object start(HttpServletRequest request,
0492: HttpServletResponse response) throws SQLException,
0493: HammurapiWebException {
0494: String interactionIdStr = request.getParameter("interactionId");
0495: if (interactionIdStr == null) {
0496: return "Interaction id is missing";
0497: }
0498:
0499: int interactionId = Integer.parseInt(interactionIdStr);
0500:
0501: InteractionFactory factory = (InteractionFactory) getGlobal(
0502: request, "db/InteractionFactory");
0503: if (factory == null) {
0504: return "Interaction factory not found";
0505: }
0506:
0507: String exitUrl = request.getParameter("EXIT_URL");
0508: if (exitUrl == null) {
0509: exitUrl = getReferrer(request);
0510: }
0511:
0512: return startInteraction(request, response, interactionId,
0513: factory, exitUrl, null);
0514: }
0515:
0516: private Object startInteraction(HttpServletRequest request,
0517: HttpServletResponse response, int interactionId,
0518: InteractionFactory factory, String exitUrl, Integer stepId)
0519: throws SQLException, HammurapiWebException {
0520:
0521: User user = (User) request.getSession().getAttribute(
0522: AuthFilter.USER);
0523:
0524: InteractionInstance instance = factory
0525: .createInteractionInstance(interactionId, exitUrl,
0526: createActionContext(request, response),
0527: user == null ? null : user.getLoginName());
0528:
0529: if (instance == null) {
0530: return "Interaction instance cannot be created";
0531: }
0532:
0533: if (stepId != null) {
0534: instance.setStepId(stepId);
0535: instance.update();
0536: }
0537:
0538: Set namesToStore = new HashSet();
0539: Enumeration pNames = request.getParameterNames();
0540: while (pNames.hasMoreElements()) {
0541: Object name = pNames.nextElement();
0542: if (!"interactionId".equals(name)
0543: && !"EXIT_URL".equals(name)) {
0544: namesToStore.add(name);
0545: }
0546: }
0547:
0548: if (!namesToStore.isEmpty()) {
0549: PropertySet ps = instance.getProperties();
0550: Iterator nit = namesToStore.iterator();
0551: while (nit.hasNext()) {
0552: String pName = (String) nit.next();
0553: StringBuffer sb = new StringBuffer();
0554: String[] values = request.getParameterValues(pName);
0555: for (int i = 0; i < values.length; ++i) {
0556: if (i > 0) {
0557: sb.append(",");
0558: }
0559: sb.append(values[i]);
0560: }
0561: String value = sb.toString();
0562: if (!isBlank(value)) {
0563: ps.set(pName, value);
0564: }
0565: }
0566: }
0567:
0568: return next(request, response, instance, null, false);
0569: }
0570:
0571: /**
0572: * Finishes "processing" step by calculating outcoming transitions,
0573: * Changes status from "processing" to "completed"
0574: * Selects the next step.
0575: * @param request
0576: * @param response
0577: * @param instance Interaction instance.
0578: * @param stepId Step instance id
0579: * @param isAutomated If this parameter is true then step is not allowed to read step-specific request parameters.
0580: * @return Error message, redirect to the next step or redirect to exitURL if interaction has completed.
0581: * @throws SQLException
0582: * @throws HammurapiWebException
0583: */
0584: private Object next(HttpServletRequest request,
0585: HttpServletResponse response, InteractionInstance instance,
0586: Integer stepId, boolean isAutomated)
0587: throws HammurapiWebException, SQLException {
0588: // Playback protection. Pass step ID as well. Rewind to that step if it is not current.
0589:
0590: if (!isAutomated) {
0591: String storeParameters = request
0592: .getParameter("storeParameters");
0593: String storeParametersNamespace = request
0594: .getParameter("storeParametersNamespace");
0595: if ("interaction".equals(storeParameters)) {
0596: PropertySet ps = instance.getProperties();
0597: if (storeParametersNamespace != null) {
0598: ps = ps.getSubset(storeParametersNamespace + "/");
0599: }
0600: parameters2Properties(request, ps);
0601: } else if ("step".equals(storeParameters)) {
0602: StepInstance this Step = (StepInstance) (stepId == null ? instance
0603: .getStepByStatus("processing")
0604: : instance.getStep(stepId.intValue()));
0605: if (this Step == null) {
0606: return "Cannot store parameters to the current interaction step - there is no step";
0607: }
0608:
0609: PropertySet ps = this Step.getProperties();
0610: if (storeParametersNamespace != null) {
0611: ps = ps.getSubset(storeParametersNamespace + "/");
0612: }
0613: parameters2Properties(request, ps);
0614: }
0615: }
0616:
0617: User user = (User) request.getSession().getAttribute(
0618: AuthFilter.USER);
0619: instance.completed(stepId, createActionContext(request,
0620: response), isAutomated ? null : user.getLoginName());
0621:
0622: InteractionInstance.StepInstance nextStep = instance
0623: .getStepByStatus("pending");
0624:
0625: if (nextStep == null) {
0626: instance.setStatus("Completed");
0627: instance
0628: .setFinishTime(new Long(System.currentTimeMillis()));
0629: instance.after(createActionContext(request, response));
0630: instance.update();
0631: return new SimpleRedirect(instance.getExitUrl(),
0632: "Interaction completed: " + instance.getId());
0633: }
0634:
0635: nextStep.setSeqId(instance.getNextSeqId());
0636: nextStep.setStatus("processing");
0637: nextStep.setStartTime(new Long(System.currentTimeMillis()));
0638: nextStep.update();
0639: String controllerUrl = response.encodeURL(request
0640: .getRequestURL().toString());
0641: if (controllerUrl.endsWith("/start")) {
0642: controllerUrl = controllerUrl.substring(0, controllerUrl
0643: .length()
0644: - "/start".length())
0645: + "/next";
0646: }
0647: String queryTail = "&interactionStep=" + nextStep.getId()
0648: + "&interactionController=" + controllerUrl;
0649:
0650: DynaBind dynaBind = nextStep.action(createActionContext(
0651: request, response));
0652:
0653: if (dynaBind != DynaBind.SKIP_BIND) {
0654: RequestContext requestContext = new RequestContext(request);
0655: StepDefinition definition = nextStep.getDefinition();
0656: String bindType = definition.getBindType();
0657: if ("URL".equals(bindType)) {
0658: PropertyParser ps = new PropertyParser(requestContext,
0659: false);
0660: String url = ps.parse(definition.getBindUrl());
0661: int idx = url.indexOf("?");
0662: url += (idx == -1 ? "?" : "&") + "interaction="
0663: + instance.getId() + queryTail;
0664: return new SimpleRedirect(url,
0665: "Redirecting to the next interaction step"); // TODO - Add interaction id or step id.
0666: }
0667:
0668: if ("Menu".equals(bindType)) {
0669: if (definition.getBindMenu() == null) {
0670: return "[Step instance " + nextStep.getId()
0671: + "] Bind menu is not set";
0672: }
0673: Menu menu = (Menu) request.getSession().getAttribute(
0674: MenuFilter.MENU_ATTRIBUTE);
0675: if (menu == null) {
0676: return "[Step instance " + nextStep.getId()
0677: + "] Root menu not found";
0678: }
0679: menu = menu.findById(definition.getBindMenu()
0680: .intValue());
0681: if (menu == null) {
0682: return "[Step instance " + nextStep.getId()
0683: + "] Bind menu is not found";
0684: }
0685: String url = (String) menu.get("href", requestContext);
0686: int idx = url.indexOf("?");
0687: url += (idx == -1 ? "?" : "&") + "interaction="
0688: + instance.getId() + queryTail;
0689: return new SimpleRedirect(url, "Redirecting to menu "
0690: + menu.getName());
0691: }
0692:
0693: if ("Interaction".equals(bindType)) {
0694: if (definition.getBindInteraction() == null) {
0695: return "[Step instance " + nextStep.getId()
0696: + "] Bind interaction is not set";
0697: }
0698: String eUrl = requestContext.get("context-path")
0699: + NEXT_STEP_URI + instance.getId() + queryTail;
0700: return startInteraction(request, response, definition
0701: .getBindInteraction().intValue(), instance
0702: .getFactory(), eUrl, new Integer(nextStep
0703: .getId()));
0704: }
0705:
0706: // Dynamic binding
0707: if ("Dynamic".equals(bindType)) {
0708: if (dynaBind instanceof DynaBind.MenuBind) {
0709: DynaBind.MenuBind menuBind = (MenuBind) dynaBind;
0710:
0711: Menu menu = (Menu) request.getSession()
0712: .getAttribute(MenuFilter.MENU_ATTRIBUTE);
0713: if (menu == null) {
0714: return "[Step instance " + nextStep.getId()
0715: + "] Root menu not found";
0716: }
0717: menu = menu.findById(menuBind.getMenuId());
0718: if (menu == null) {
0719: return "[Step instance " + nextStep.getId()
0720: + "] Bind menu is not found";
0721: }
0722: String url = (String) menu.get("href",
0723: requestContext);
0724: int idx = url.indexOf("?");
0725: url += (idx == -1 ? "?" : "&") + "interaction="
0726: + instance.getId() + queryTail;
0727: return new SimpleRedirect(url,
0728: "Redirecting to menu " + menu.getName());
0729: }
0730:
0731: if (dynaBind instanceof DynaBind.InteractionBind) {
0732: DynaBind.InteractionBind interactionBind = (InteractionBind) dynaBind;
0733: String eUrl = requestContext.get("context-path")
0734: + NEXT_STEP_URI + instance.getId()
0735: + queryTail;
0736: return startInteraction(request, response,
0737: interactionBind.getInteractionId(),
0738: instance.getFactory(), eUrl, new Integer(
0739: nextStep.getId()));
0740: }
0741:
0742: if (dynaBind instanceof DynaBind.UrlBind) {
0743: DynaBind.UrlBind urlBind = (UrlBind) dynaBind;
0744: String url = urlBind.getUrl();
0745: int idx = url.indexOf("?");
0746: url += (idx == -1 ? "?" : "&") + "interaction="
0747: + instance.getId() + queryTail;
0748: return new SimpleRedirect(url,
0749: "Redirecting to the next interaction step"); // TODO - Add interaction id or step id.
0750: }
0751: }
0752: }
0753:
0754: return next(request, response, instance, new Integer(nextStep
0755: .getId()), true); // Automated step
0756: }
0757:
0758: /**
0759: * Stores request parameters to property set.
0760: * @param request
0761: * @param ps
0762: */
0763: private void parameters2Properties(HttpServletRequest request,
0764: PropertySet ps) {
0765: Enumeration pNames = request.getParameterNames();
0766: while (pNames.hasMoreElements()) {
0767: String pName = (String) pNames.nextElement();
0768: StringBuffer sb = new StringBuffer();
0769: String[] values = request.getParameterValues(pName);
0770: for (int i = 0; i < values.length; ++i) {
0771: if (i > 0) {
0772: sb.append(",");
0773: }
0774: sb.append(values[i]);
0775: }
0776: String value = sb.toString();
0777: if (!isBlank(value)) {
0778: ps.set(pName, value);
0779: }
0780: }
0781: }
0782:
0783: /**
0784: * Proceeds to the next interaction step.
0785: * Parameters:
0786: * step_id - ID of step instance which has been processed.
0787: *
0788: * @param request
0789: * @param response
0790: * @throws SQLException
0791: * @throws NumberFormatException
0792: * @throws HammurapiWebException
0793: */
0794: public Object next(HttpServletRequest request,
0795: HttpServletResponse response) throws NumberFormatException,
0796: SQLException, HammurapiWebException {
0797: String idStr = request.getParameter("interactionInstance");
0798: if (idStr == null) {
0799: return "Interaction instance ID is missing";
0800: }
0801:
0802: InteractionFactory factory = (InteractionFactory) getGlobal(
0803: request, "db/InteractionFactory");
0804: if (factory == null) {
0805: return "Interaction factory not found";
0806: }
0807:
0808: InteractionInstance instance = factory
0809: .getInteractionInstance(Integer.parseInt(idStr));
0810: if (instance == null) {
0811: return "Invalid interaction instance ID";
0812: }
0813:
0814: String stepIdStr = request.getParameter("interactionStep");
0815: Integer stepId = stepIdStr == null ? null : new Integer(
0816: stepIdStr);
0817:
0818: return next(request, response, instance, stepId, false);
0819: }
0820:
0821: /**
0822: * Creates web action context.
0823: * @param request
0824: * @param response
0825: * @return
0826: */
0827: public static Map createActionContext(HttpServletRequest request,
0828: HttpServletResponse response) {
0829: Map ret = new HashMap();
0830: ret.put("requestContext", new RequestContext(request));
0831: ret.put("request", request);
0832: ret.put("response", response);
0833: ret.put(MenuFilter.CE_GLOBAL, request.getAttribute("global"));
0834: HttpSession session = request.getSession();
0835: Object menu = session.getAttribute(MenuFilter.MENU_ATTRIBUTE);
0836: if (menu != null) {
0837: ret.put("menu", menu);
0838: }
0839: Object user = session.getAttribute(AuthFilter.USER);
0840: if (user != null) {
0841: ret.put("user", user);
0842:
0843: }
0844: Object authProvider = session
0845: .getAttribute(AuthFilter.AUTHORIZATION_PROVIDER);
0846: if (authProvider != null) {
0847: ret.put("authorizationProvider", authProvider);
0848: }
0849:
0850: ret.put("converter", converter);
0851: return ret;
0852: }
0853:
0854: /**
0855: * Returns list of menus with interactions for AJAX tree.
0856: * @param request
0857: * @param response
0858: * @param servlet
0859: * @return
0860: * @throws SQLException
0861: * @throws
0862: * @throws SQLException
0863: * @throws ConfigurationException
0864: */
0865: public Object getMenu(HttpServletRequest request,
0866: HttpServletResponse response) throws SQLException {
0867: String parent = request.getParameter("parentId");
0868: MenuEngine engine = MenuActions.getEngine(request);
0869: Map ret = new HashMap();
0870: if (parent == null) {
0871: String targetForm = request.getParameter("targetForm");
0872: if (targetForm != null) {
0873: ret.put("targetForm", targetForm);
0874: }
0875:
0876: String targetField = request.getParameter("targetField");
0877: if (targetField != null) {
0878: ret.put("targetField", targetField);
0879: }
0880:
0881: ret.put("items", engine.getRootMenus(new ArrayList()));
0882: } else {
0883: int parentInt = Integer.parseInt(parent);
0884: ret.put("items", engine.getMenuWithChildCount(parentInt,
0885: new ArrayList()));
0886: ret.put("interactions", getEngine(request)
0887: .getInteractionByOwner(parentInt, new ArrayList()));
0888: ret.put("path", MenuActions.path(parent, engine));
0889: }
0890: return ret;
0891: }
0892:
0893: /**
0894: * Menu/interaction path
0895: * @param request
0896: * @param response
0897: * @param servlet
0898: * @return
0899: * @throws NumberFormatException
0900: * @throws SQLException
0901: */
0902: public String path(HttpServletRequest request,
0903: HttpServletResponse response) throws NumberFormatException,
0904: SQLException {
0905: String idStr = request.getParameter("id");
0906: if (idStr == null) {
0907: return "Id parameter is missing";
0908: }
0909:
0910: return path(request, idStr);
0911: }
0912:
0913: private String path(HttpServletRequest request, String idStr)
0914: throws SQLException {
0915: MenuEngine engine = MenuActions.getEngine(request);
0916:
0917: if (idStr.startsWith(INTERACTION_PREFIX)) {
0918: int interactionId = Integer.parseInt(idStr
0919: .substring(INTERACTION_PREFIX.length()));
0920: Interaction interaction = getEngine(request)
0921: .getInteraction(interactionId);
0922: if (interaction == null) {
0923: return "Invalid interaction ID";
0924: }
0925:
0926: return MenuActions.path(String.valueOf(interaction
0927: .getOwnerMenu()), engine)
0928: + " : " + interaction.getName();
0929: }
0930:
0931: return MenuActions.path(idStr, engine);
0932: }
0933:
0934: public Object updateBindings(HttpServletRequest request,
0935: HttpServletResponse response) throws NumberFormatException,
0936: SQLException {
0937: Enumeration penum = request.getParameterNames();
0938: InteractionEngine engine = getEngine(request);
0939: while (penum.hasMoreElements()) {
0940: String pName = (String) penum.nextElement();
0941: if (pName.startsWith(BIND_TYPE_PREFIX)) {
0942: String stepIdStr = pName.substring(BIND_TYPE_PREFIX
0943: .length());
0944: InteractionStep step = engine
0945: .getInteractionStep(Integer.parseInt(stepIdStr));
0946: if (step == null) {
0947: return "Step not found: " + stepIdStr;
0948: }
0949: String bindType = request.getParameter(pName);
0950: if ("Menu/Interaction".equals(bindType)) {
0951: String bindIdStr = request
0952: .getParameter("BIND_MENU_INTERACTION_"
0953: + stepIdStr);
0954: if (bindIdStr.startsWith(INTERACTION_PREFIX)) {
0955: step.setBindType("Interaction");
0956: step
0957: .setBindInteraction(new Integer(
0958: bindIdStr
0959: .substring(INTERACTION_PREFIX
0960: .length())));
0961: } else {
0962: step.setBindType("Menu");
0963: step.setBindMenu(new Integer(bindIdStr));
0964: }
0965: } else {
0966: step.setBindType(bindType);
0967: if ("URL".equals(bindType)) {
0968: step.setBindUrl(request
0969: .getParameter("BIND_URL_" + stepIdStr));
0970: if (isBlank(step.getBindUrl())) {
0971: return "Bind URL is blank for step "
0972: + step.getName();
0973: }
0974: }
0975: }
0976: engine.updateInteractionStep(step);
0977: }
0978: }
0979:
0980: String referrer = getReferrer(request);
0981: if (referrer == null) {
0982: Menu menu = (Menu) request.getSession().getAttribute(
0983: MenuFilter.MENU_ATTRIBUTE);
0984: referrer = menu == null ? null : (String) menu.findByXid(
0985: "menu.Interaction.list").get("href",
0986: new RequestContext(request));
0987: if (referrer == null) {
0988: return "Interaction bindings updated";
0989: }
0990: }
0991:
0992: InteractionFactory factory = (InteractionFactory) getGlobal(
0993: request, "db/InteractionFactory");
0994: if (factory != null) {
0995: factory.invalidateInteractions();
0996: }
0997:
0998: return new SimpleRedirect(referrer,
0999: "Ineraction bindings updated");
1000: }
1001:
1002: /**
1003: * Returns XML-ized interaction instance for rendering.
1004: * Parameters: ID - instance ID.
1005: *
1006: * @param request
1007: * @param response
1008: * @throws SQLException
1009: * @throws NumberFormatException
1010: */
1011: public Object getInstanceXml(HttpServletRequest request,
1012: HttpServletResponse response) throws SQLException {
1013: String idStr = request.getParameter("interaction");
1014: if (idStr == null) {
1015: return "'interaction' parameter is missing";
1016: }
1017:
1018: InteractionFactory factory = (InteractionFactory) getGlobal(
1019: request, "db/InteractionFactory");
1020: if (factory == null) {
1021: return "Interaction factory not found";
1022: }
1023:
1024: return factory.getInteractionInstance(Integer.parseInt(idStr));
1025: }
1026:
1027: /**
1028: * Retrieves interaction instance using interaction factory and request parameters
1029: * @param request
1030: * @return
1031: * @throws HammurapiWebException
1032: * @throws NumberFormatException
1033: * @throws SQLException
1034: */
1035: public static InteractionInstance getInstance(Context ctx)
1036: throws HammurapiWebException, SQLException {
1037: String idStr = (String) ctx.get("param:interaction");
1038: if (idStr == null) {
1039: throw new HammurapiWebException(
1040: "Interaction instance ID is missing");
1041: }
1042:
1043: InteractionFactory factory = (InteractionFactory) ctx
1044: .get("global:db/InteractionFactory");
1045: if (factory == null) {
1046: throw new HammurapiWebException(
1047: "Interaction factory not found");
1048: }
1049:
1050: InteractionInstance instance = factory
1051: .getInteractionInstance(Integer.parseInt(idStr));
1052: if (instance == null) {
1053: throw new HammurapiWebException(
1054: "Invalid interaction instance ID");
1055: }
1056: return instance;
1057: }
1058:
1059: /**
1060: * Retrieves current interaction step from the interaction factory and request parameters.
1061: * @param request
1062: * @return
1063: * @throws HammurapiWebException
1064: * @throws SQLException
1065: * @throws NumberFormatException
1066: */
1067: public static InteractionInstance.StepInstance getCurrentStep(
1068: Context ctx) throws HammurapiWebException,
1069: NumberFormatException, SQLException {
1070: String stepIdStr = (String) ctx.get("param:interactionStep");
1071: InteractionInstance.StepInstance ret;
1072: InteractionInstance instance = getInstance(ctx);
1073: if (stepIdStr == null) {
1074: ret = instance.getStepByStatus("processing");
1075: } else {
1076: ret = instance.getStep(Integer.parseInt(stepIdStr));
1077: }
1078:
1079: if (ret == null) {
1080: throw new HammurapiWebException("Current step is not found");
1081: }
1082:
1083: return ret;
1084: }
1085:
1086: /**
1087: * Menu/interaction path
1088: * @param request
1089: * @param response
1090: * @param servlet
1091: * @return
1092: * @throws NumberFormatException
1093: * @throws SQLException
1094: */
1095: public Object generate(HttpServletRequest request,
1096: HttpServletResponse response) throws SQLException,
1097: IOException {
1098: SQLProcessor processor = (SQLProcessor) getGlobal(request,
1099: "sql-processor");
1100: String[] stepIds = request.getParameterValues("GENERATE");
1101: Reader r = new InputStreamReader(this .getClass()
1102: .getResourceAsStream("generatedContent.jxp"));
1103: StringWriter sw = new StringWriter();
1104: char[] buf = new char[512];
1105: int l;
1106: while ((l = r.read(buf)) != -1) {
1107: sw.write(buf, 0, l);
1108: }
1109: r.close();
1110: sw.close();
1111: String content = sw.toString();
1112: for (int i = 0; i < stepIds.length; ++i) {
1113: processor.executeTransaction(generatePage(Integer
1114: .parseInt(stepIds[i]), request, content));
1115: }
1116:
1117: return new SimpleRedirect("getXml/interaction/view.html",
1118: "Interaction pages has been successfully generated");
1119: }
1120:
1121: private Transaction generatePage(final int stepId,
1122: final HttpServletRequest request, final String content) {
1123: return new Transaction() {
1124:
1125: public boolean execute(SQLProcessor processor)
1126: throws SQLException {
1127: IdentityManager identityManager = (IdentityManager) getGlobal(
1128: request, "db/IdentityManager");
1129: Connection con = processor.getConnection();
1130: SQLProcessor cprc = new SQLProcessor(con, null);
1131: InteractionEngine engine = new InteractionEngine(cprc);
1132: InteractionStep step = engine
1133: .getInteractionStep(stepId);
1134:
1135: XmenuImpl menu = new XmenuImpl(false);
1136: MenuEngine menuEngine = new MenuEngine(cprc);
1137:
1138: GuidGenerator guidGenerator = (GuidGenerator) getGlobal(
1139: request, "db/guid-generator");
1140: if (guidGenerator != null) {
1141: try {
1142: menu.setGuid(guidGenerator.nextGUID());
1143: } catch (HammurapiWebException e) {
1144: throw new SQLExceptionEx(e);
1145: }
1146: }
1147:
1148: menu.setContent(content);
1149: menu.setName(request.getParameter("NAME_" + stepId));
1150: menu.setDescription(request.getParameter("DESCRIPTION_"
1151: + stepId));
1152: menu.setTitle(request.getParameter("TITLE_" + stepId));
1153: menu.setScope("Interaction");
1154: menu.setContentType("Jxp");
1155: menu.setType("Item");
1156:
1157: String parent = request.getParameter("PARENT");
1158: if (parent != null) {
1159: menu.setParent(new Integer(parent));
1160: }
1161:
1162: if (identityManager instanceof IdentityGenerator) {
1163: menu.setId(((IdentityGenerator) identityManager)
1164: .generate(con, "XMENU"));
1165: }
1166:
1167: menuEngine.insertXmenu(menu);
1168:
1169: if (identityManager instanceof IdentityRetriever) {
1170: menu.setId(((IdentityRetriever) identityManager)
1171: .retrieve(con));
1172: }
1173:
1174: HelpTopic mainTopic = new HelpTopicImpl(false);
1175: mainTopic.setContent(menu.getDescription());
1176: mainTopic.setName("main");
1177: mainTopic.setMenuId(menu.getId());
1178: mainTopic.setLastModified(System.currentTimeMillis());
1179: mainTopic.setRenderTemplate("AjaxTooltip");
1180: mainTopic.setType("Content");
1181: menuEngine.insertHelpTopic(mainTopic);
1182:
1183: step.setBindType("Menu");
1184: step.setBindMenu(new Integer(menu.getId()));
1185: engine.updateInteractionStep(step);
1186:
1187: return true;
1188: }
1189:
1190: };
1191: }
1192:
1193: }
|