public IDfSessionManager getMrcsSystemUserSession(Map parameters, String mrcsapp)
      throws Exception {
    /*-CONFIG-*/ String m = "getMrcsSystemUserSession - ";
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "accessing config factory...", null, null);
    StateTransitionConfigFactory sts = StateTransitionConfigFactory.getSTConfig();

    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "looking up app's system user for mrcsapp " + mrcsapp, null, null);
    String sysuser = sts.getSystemUsername(mrcsapp);
    String syspass = sts.getSystemPassword(mrcsapp);

    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "creating DCTM client object", null, null);
    IDfClient client = DfClient.getLocalClient();

    String docbase = ((String[]) parameters.get("docbase_name"))[0];

    IDfSessionManager sMgr = null;
    DfLoginInfo loginInfo = new DfLoginInfo();
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "setting identity to mrcs sysuser " + sysuser, null, null);
    loginInfo.setUser(sysuser);
    loginInfo.setPassword(syspass);
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "getting MRCS sysuser session for mrcsapp", null, null);
    sMgr = client.newSessionManager();
    sMgr.setIdentity(docbase, loginInfo);
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "returning", null, null);
    return sMgr;
  }
 // this one scans the mrcsapplications for the given workflow, task pair, assumes workflow is
 // uniquely named across mrcsapps
 public Map getTaskConfiguration(String workflow, String task) {
   /*-CONFIG-*/ String m = "getTaskConfiguration - ";
   /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
     DfLogger.debug(this, m + "accessing config factory...", null, null);
   StateTransitionConfigFactory sts = StateTransitionConfigFactory.getSTConfig();
   /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
     DfLogger.debug(this, m + "task: " + task, null, null);
   /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
     DfLogger.debug(this, m + "workflow: " + workflow, null, null);
   /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
     DfLogger.debug(this, m + "scanning mrcsapps for workflow match", null, null);
   Map config = sts.getUniqueWorkflowTaskMethodConfiguration(workflow, task);
   return config;
 }
 public Map getTaskConfiguration(String mrcsapp, String workflow, String task) {
   /*-CONFIG-*/ String m = "getTaskConfiguration - ";
   /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
     DfLogger.debug(this, m + "accessing config factory...", null, null);
   StateTransitionConfigFactory sts = StateTransitionConfigFactory.getSTConfig();
   /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
     DfLogger.debug(this, m + "mrcsapp: " + mrcsapp, null, null);
   /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
     DfLogger.debug(this, m + "task: " + task, null, null);
   /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
     DfLogger.debug(this, m + "workflow: " + workflow, null, null);
   /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
     DfLogger.debug(this, m + "looking up task detail for above criteria", null, null);
   MrcsWorkflowTask taskdetail = sts.getMrcsWorkflowTask(mrcsapp, workflow, task);
   return taskdetail.MethodConfiguration;
 }
  public boolean onCommitChanges() {
    /*-CONFIG-*/ String m = "onCommitChanges-";

    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "get State Transition config", null, null);
    StateTransitionConfigFactory config = StateTransitionConfigFactory.getSTConfig();
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "get MRCS config task definition", null, null);
    MrcsWorkflowTask t = config.getMrcsWorkflowTask(m_mrcsapp, m_processname, m_taskname);

    boolean canCommit = false;
    try {
      AutoSelectSinglePath();

      // perform basic CFR part 11 checks: must have valid user/pass/reason, user is user that is
      // logged in, password is valid, reason is not empty/null
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "check form and user/pass/reason validations", null, null);
      String validation = performValidation();
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(
            this, m + "result: " + (validation == null ? "valid" : validation), null, null);
      if (validation != null) {
        /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
          DfLogger.debug(this, m + "User/Pass/Reason error detected: " + validation, null, null);
        setErrorMessage(validation);
        return false;
      }

      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "get refs to signing controls", null, null);
      Text usernameCtrl = (Text) getControl(QADocForwardWFT.USERNAME_CONTROL_NAME, Text.class);
      Password passwordCtrl =
          (Password) getControl(QADocForwardWFT.PASSWORD_CONTROL_NAME, Password.class);
      DropDownList rsnListCtrl =
          (DropDownList) getControl(QADocForwardWFT.REASONSELECT_CONTROL_NAME, DropDownList.class);
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "get refs to signing controls", null, null);
      String username = usernameCtrl.getValue();
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + " -- user: "******" -- pass: "******"null" : "#########"), null, null);
      String reason = rsnListCtrl.getValue();
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + " -- reason: " + reason, null, null);

      // HACK the class hierarchy: set Password on superclass, otherwise it won't successfully
      // complete when calling super.onCommitChanges()
      Password passwdCtrl = (Password) getControl("__PASSWORD_CONTROL_NAME");
      passwdCtrl.setValue(password);

      try {
        /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
          DfLogger.debug(this, m + "check for signature validations", null, null);
        if (t.MethodConfiguration != null
            && t.MethodConfiguration.containsKey("SignatureValidations")) {
          /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
            DfLogger.debug(this, m + "signature validations detected", null, null);
          List signvalidations = (List) t.MethodConfiguration.get("SignatureValidations");
          Map context = new HashMap();
          List errmsgs = new ArrayList();
          boolean vflag = false;
          for (int i = 0; i < signvalidations.size(); i++) {
            /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
              DfLogger.debug(this, m + "running signing validation plugin #" + i, null, null);
            MrcsPlugin plugin = (MrcsPlugin) signvalidations.get(i);
            /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
              DfLogger.debug(this, m + "-- instantiating - " + plugin.PluginClassName, null, null);
            // we'll reuse IMrcsWorkflowValidation as the plugin interface, even though it lacks the
            // task name, which I guess we could hardcode in the MRCS config for the task if need
            // be...
            ISignatureValidation vplug =
                (ISignatureValidation) Class.forName(plugin.PluginClassName).newInstance();
            /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
              DfLogger.debug(this, m + "-- exec", null, null);
            if (!vplug.validate(
                getDfSession().getSessionManager(),
                getDfSession().getDocbaseName(),
                m_mrcsapp,
                m_processname,
                m_task,
                m_primarypackage,
                username,
                password,
                reason,
                errmsgs,
                plugin.PluginConfiguration,
                context)) {
              // break immediately? Or run through all of them?
              vflag = false;
              /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
                DfLogger.debug(this, m + "-- VALIDATION FAILURE", null, null);
              break;
            }
          }
          if (vflag) // validation failed if true...
          {
            for (int ii = 0; ii < errmsgs.size(); ii++) setErrorMessage((String) errmsgs.get(ii));
            return false;
          }
        }
      } catch (Exception e) {
        /*-ERROR-*/ DfLogger.error(this, m + "Error in Signature Validations", null, e);
        throw new WrapperRuntimeException(e);
      }

      // now, I'm pretty sure that super.canCommitChanges() is a dangerous point-of-no-return call
      // that actually has side effects, despite its stateless-implying name,
      // so we should make sure as we can that the signing info has been verified at this point, by
      // checking audit records, rendition presence, number of signatures, etc
      if (super.canCommitChanges()) {
        // I'm pretty sure this super.onCommitChanges call is point-of-no-return: the task will be
        // completed and the workflow will proceed with the next task
        // if they are automatic. This can create race conditions with stuff that happens after the
        // task is done, such as workflow plugins, etc. If you get an error
        // message with "can't find object reference" of something like 4d017f38XXXXX, then the
        // workflow completed and cleaned itself before the plugins/signing
        // could complete in time.

        // THEREFORE, we will sign first (signing multiple documents can take...awhile...), THEN
        // commit changes
        if (m_task.isSignOffRequired()) {
          /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
            DfLogger.debug(
                this,
                m
                    + "onCommitChanges is signing the document - I don't think this should ever happen for FinishWFT",
                null,
                null);
          try {
            if (t.MethodConfiguration != null
                && t.MethodConfiguration.containsKey("SignatureService")) {
              MrcsPlugin signingplugin = (MrcsPlugin) t.MethodConfiguration.get("SignatureService");
              ISignatureService signplug =
                  (ISignatureService) Class.forName(signingplugin.PluginClassName).newInstance();
              /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
                DfLogger.debug(this, m + "-- exec signing", null, null);
              signplug.sign(
                  getDfSession().getSessionManager(),
                  getDfSession().getDocbaseName(),
                  m_mrcsapp,
                  m_processname,
                  m_task,
                  m_primarypackage,
                  username,
                  password,
                  reason,
                  signingplugin.PluginConfiguration,
                  null);
            }
          } catch (Exception e) {
            /*-ERROR-*/ DfLogger.error(this, m + "Error in Signature Service", null, e);
            throw new WrapperRuntimeException(e);
          }
        }

        canCommit = super.onCommitChanges();
        /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
          DfLogger.debug(
              this,
              m + "canCommit (after validation and performing super call) : " + canCommit,
              null,
              null);
      } else {
        canCommit = false;
      }
      if (canCommit) {

        // uses Actions as a pluginlayer...
        // IN GENERAL these are a bad idea, due to the race conditions documented in the comments
        // above...
        /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
          DfLogger.debug(
              this, " MRCS:FinishWFT: onCommitChanges : get ref to workflow defn", null, null);
        IDfId workflowid = m_task.getWorkflowId();
        /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
          DfLogger.debug(
              this,
              " MRCS:FinishWFT: onCommitChanges : look up workflow object (IDfWorkflow)",
              null,
              null);
        IDfWorkflow workflow = (IDfWorkflow) getDfSession().getObject(workflowid);
        /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
          DfLogger.debug(
              this,
              " MRCS:FinishWFT: onCommitChanges : look up process object (IDfProcess)",
              null,
              null);
        IDfProcess wfdef = (IDfProcess) getDfSession().getObject(workflow.getProcessId());
        /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
          DfLogger.debug(
              this,
              " MRCS:FinishWFT: onCommitChanges : workflow name: " + wfdef.getObjectName(),
              null,
              null);
        MrcsWorkflowTask mrcstask =
            config.getMrcsWorkflowTask(m_mrcsapp, wfdef.getObjectName(), m_task.getTaskName());
        if (mrcstask.Actions != null) {
          Map context = new HashMap();
          /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
            DfLogger.debug(
                this,
                " MRCS:FinishWFT: onCommitChanges : executing client-side plugins",
                null,
                null);
          for (int k = 0; k < mrcstask.Actions.size(); k++) {
            try {
              /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
                DfLogger.debug(
                    this,
                    " MRCS:FinishWFT: onCommitChanges : executing plugin " + (k + 1),
                    null,
                    null);
              MrcsPlugin plugin = (MrcsPlugin) mrcstask.Actions.get(k);
              /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
                DfLogger.debug(
                    this,
                    " MRCS:FinishWFT: onCommitChanges : -- class: " + plugin.PluginClassName,
                    null,
                    null);
              IMrcsWorkflowActionPlugin wfaction =
                  (IMrcsWorkflowActionPlugin) Class.forName(plugin.PluginClassName).newInstance();
              wfaction.execute(
                  getDfSession().getSessionManager(),
                  getDfSession().getDocbaseName(),
                  m_task,
                  workflow,
                  m_mrcsapp,
                  plugin.PluginConfiguration,
                  context);
            } catch (Exception e) {
              /*-ERROR-*/ DfLogger.error(
                  this, m + "error in MRCS 4.2 client-side workflow actions", null, e);
              setErrorMessage("MSG_UNEXPECTED_ERROR", new Object[] {e.getMessage()}, e);
              throw new WrapperRuntimeException("error in MRCS workflow actions", e);
            }
          }
        }
        if (canCommit)
          setMessage("MSG_FINISH_SUCCESS", new Object[] {super.getString("MSG_OBJECT")});
      } // commit & esign ends
    } catch (DfException e1) {
      /*-ERROR-*/ DfLogger.error(
          this, "MRCS:FinishWFT.onCommitChanges - DfException occurred: ", null, e1);
      canCommit = false;
      try {
        if (m_task.getCompleteErrStatus() == 4) {
          /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
            DfLogger.debug(this, m + "Exception occurred:Incorrect Password " + e1, null, null);
          setErrorMessage("MSG_INCORRECT_PASSWORD");
          return false;
        }
        /*
         * else if(){ [DM_SYSOBJECT_E_ESIGN_SIGNATURE_METHOD_FAILED }
         */
        else {
          /*-ERROR-*/ DfLogger.error(
              this,
              "MRCS:FinishWFT.onCommitChanges - Exception occurred:Unexpected Error ",
              null,
              e1);
          setErrorMessage("MSG_UNEXPECTED_ERROR", new Object[] {e1.getMessage()}, e1);
          return false;
        }
      } catch (DfException e2) {
        /*-ERROR-*/ DfLogger.error(this, m + "error in exception handling code", null, e2);
        throw new WrapperRuntimeException(e2);
      }
    }

    return canCommit;
  }
  String performValidation() throws DfException {
    /*-CONFIG-*/ String m = "performValidation-";
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "Check if task requires signoff", null, null);
    if (m_task.isSignOffRequired()) {
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "flipping on validation", null, null);
      setDoValidation(true);

      // need to check forwarding paths' checkboxes for: at least one checked
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(
            this, m + "checking forwarding checkbox datagrid for at-least-one-checked", null, null);
      Datagrid forwardgrid =
          (Datagrid) getControl(ForwardWorkflowTask.NEXT_TASKS_GRID_CONTROL_NAME);
      Iterator i = forwardgrid.getContainedControls();
      // this seems to be infinitely looped, <sarcasm>Nice Iterator guys</sarcasm> <shrug>then
      // again, I've seen it not infinitely looped...</shrug>
      HashSet resultset =
          new HashSet(); // for tracking what we've seen and haven't seen yet so we can tell when
      // the infinitely looping iterator has looped back around
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(
            this,
            m
                + "iterating through controls, adding them to our set of checkboxes if they are of type checkbox",
            null,
            null);
      while (i.hasNext()) {
        Control current = (Control) i.next();
        if (current instanceof DatagridRow) {
          DatagridRow row = (DatagridRow) current;
          Iterator cboxes = row.getContainedControls();
          String cboxname = "";
          while (cboxes.hasNext()) {
            Control subcurrent = (Control) cboxes.next();
            if (subcurrent instanceof Checkbox) {
              cboxname = subcurrent.getName();
              /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
                DfLogger.debug(this, m + "found cbox named " + cboxname, null, null);
              break; // break from datagridrow's infinite iterator
            }
          }
          // check if we've seen this checkbox before...
          if (resultset.contains(cboxname)) break; // break from datagrid's infinite iterator
          else {
            // we haven't, so add this to the list/set of checkboxes and keep looking for new
            // checkboxes
            resultset.add(cboxname);
            /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
              DfLogger.debug(
                  this, m + "adding cbox named to cbox search results" + cboxname, null, null);
          }
        }
      }
      // okay, now we should have a list of checkbox control names we can validate...that was
      // entirely too complicated
      // CEM: this seems to be the only place that reliably can access the forward paths grid. Do
      // auto-select for single path option sets.
      int checkedcount = 0;
      int boxcount = 0;
      Checkbox firstcbox = null;
      boolean forwardPathValidation = false;
      Iterator foundcboxesiterator = resultset.iterator();
      while (foundcboxesiterator.hasNext()) {
        String name = (String) foundcboxesiterator.next();
        /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
          DfLogger.debug(this, m + "examining checkbox: " + name, null, null);
        Checkbox cbox = (Checkbox) getControl(name);
        if (0 == boxcount) firstcbox = cbox;
        boxcount++;
        if (cbox.getValue()) {
          /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
            DfLogger.debug(this, m + "checkbox is checked: " + name, null, null);
          forwardPathValidation = true;
          /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
            DfLogger.debug(this, m + "iterating checkedcount", null, null);
          checkedcount++;
          /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
            DfLogger.debug(this, m + "checkedcount is " + checkedcount, null, null);
        }
      }
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "check for autoselect of single forward path", null, null);
      if (1 == boxcount) {
        // TODO: does this interfere with reject? --> I would guess that reject triggers a RejectWFT
        // object, not this one....
        /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
          DfLogger.debug(this, m + "autochecking the single forward path", null, null);
        if (!firstcbox.getValue()) {
          firstcbox.setValue(true);
          checkedcount++;
        }
        forwardPathValidation = true;
      }

      if (forwardPathValidation == false) {
        return "MSG_FORWARD_PATH_NOT_SELECTED";
      }

      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "get State Transition config", null, null);
      StateTransitionConfigFactory config = StateTransitionConfigFactory.getSTConfig();
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "get MRCS config task definition", null, null);
      MrcsWorkflowTask t = config.getMrcsWorkflowTask(m_mrcsapp, m_processname, m_taskname);

      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(
            this,
            m + "validating checked forward path count, # selected: " + checkedcount,
            null,
            null);
      // MJH 8-29-2006: updated workflow object to be IDfWorkflow from IDfSysobject, threw CCE in
      // 5.3
      IDfProcess workflow = (IDfProcess) getDfSession().getObject(m_task.getProcessId());
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "workflow system name: " + workflow.getObjectName(), null, null);
      if (!config.doesWorkflowTaskAllowMultiplePaths(
          m_mrcsapp, workflow.getObjectName(), m_task.getTaskName())) {
        if (checkedcount > 1) {
          /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
            DfLogger.debug(
                this, m + "more than one path selected when only one is allowed", null, null);
          return "MSG_MULTIPLE_PATHS_SELECTED_WHEN_ONLY_ONE_ALLOWED";
        }
      }

      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "get refs to signing controls", null, null);
      Text usernameCtrl = (Text) getControl(QADocFinishWFT.USERNAME_CONTROL_NAME, Text.class);
      Password passwordCtrl =
          (Password) getControl(QADocFinishWFT.PASSWORD_CONTROL_NAME, Password.class);
      DropDownList rsnListCtrl =
          (DropDownList) getControl(QADocFinishWFT.REASONSELECT_CONTROL_NAME, DropDownList.class);
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "get refs to signing controls", null, null);
      String username = usernameCtrl.getValue();
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + " -- user: "******" -- pass: "******"null" : "#########"), null, null);
      String reason = rsnListCtrl.getValue();
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + " -- reason: " + reason, null, null);

      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "calling super.validate()", null, null);
      validate();
      if (!getIsValid()) {
        return "MSG_FORM_VALIDATION";
      }
      // if ((usrName != null) && (pswd != null) && (rsn)) {
      if ((username != null)
          && (username.trim().length() > 0)
          && (password != null)
          && (reason != null)) {
        // CEM: weird bug - if password is correct, but username is wrong, then the task completes
        // but fails when we sign -- after webtop has completed the task.
        //      - so make sure the user matches the session user!
        String loggedinusername =
            getDfSession()
                .getSessionManager()
                .getIdentity(getDfSession().getDocbaseName())
                .getUser();
        if (!loggedinusername.equals(username)) {
          /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
            DfLogger.debug(this, m + "entered username does not match current user", null, null);
          return "MSG_USERNAME_MISMATCH";
        } else {
          // apparently we need to ensure the password is correct...
          IDfLoginInfo logininfo = new DfLoginInfo();
          logininfo.setUser(username);
          logininfo.setPassword(password);
          try {
            getDfSession().authenticate(logininfo);
          } catch (DfAuthenticationException authex) {
            // return code via exception...great design, guys
            return "MSG_BAD_PASSWORD";
          }
        }

      } else {
        return "MSG_MISSING_USER_PASS_REASON";
      }
    }
    return null;
  }
  // implement the default configurable method - execute listed actions in workflow task
  public void execute(Map parameters, OutputStream outputstream) throws Exception {
    /*-CONFIG-*/ String m = "MrcsConfigurableMethod.execute - ";

    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "getting docbase from JSM parameters", null, null);
    String[] paramvals = (String[]) parameters.get("docbase_name");
    String docbase = paramvals[0];
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "  ~~docbase: " + docbase, null, null);
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "getting packageId from JSM parameters", null, null);
    paramvals =
        (String[])
            parameters.get(
                "packageId"); // OOTB docbasic promote method thinks this is workitemid...
    String packageid = paramvals[0];
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "  ~~packageId: " + packageid, null, null);
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "getting 'mode' from JSM parameters", null, null);
    paramvals = (String[]) parameters.get("mode");
    String mode = paramvals[0];
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "  ~~MODE: " + mode, null, null);

    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "getting mrcs system session", null, null);
    IDfSessionManager sessionmgr = getMrcsSystemUserSessionFromFirstAttachment(parameters);
    IDfSession session = sessionmgr.getSession(docbase);
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "session DMCL id: " + session.getDMCLSessionId(), null, null);

    // get workitem
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "retreive workitem (the 'packageid')", null, null);
    IDfWorkitem workitem = (IDfWorkitem) session.getObject(new DfId(packageid));
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(
          this, m + "...retrieved workitem " + packageid + "? " + (workitem != null), null, null);

    // acquire if not mode 0. ?what? - it's what the docbasic thingy does
    if ("0".equals(mode)) {
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "mode is 0, acquiring workitem...", null, null);
      workitem.acquire();
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "...acquired", null, null);
    }
    try {

      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "get attachment", null, null);
      IDfSysObject attachment = getFirstAttachment(sessionmgr, parameters);
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "mrcsapplication of attachment", null, null);
      String mrcsapp = attachment.getString("mrcs_application");
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + " -- is: " + mrcsapp, null, null);

      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "get workflow object " + workitem.getWorkflowId(), null, null);
      IDfWorkflow workflow = (IDfWorkflow) session.getObject(workitem.getWorkflowId());

      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "get process object " + workflow.getProcessId(), null, null);
      IDfProcess process = (IDfProcess) session.getObject(workflow.getProcessId());

      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "workflow process name and task name", null, null);
      String workflowname = process.getObjectName();
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "-- workflow process name: " + workflowname, null, null);
      String taskname = workitem.getActivity().getObjectName();
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "-- workitem activity name: " + taskname, null, null);

      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "locate configuration of task in mrcs config", null, null);
      StateTransitionConfigFactory stconfig = StateTransitionConfigFactory.getSTConfig();

      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "look up MRCS task definition", null, null);
      MrcsWorkflowTask mrcstask = stconfig.getMrcsWorkflowTask(mrcsapp, workflowname, taskname);

      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(
            this,
            m + "getting server plugins list (ServerPlugins key in the MethodConfiguration)",
            null,
            null);
      List actionlist = (List) mrcstask.MethodConfiguration.get("ServerPlugins");

      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "EXEC plugins", null, null);
      if (actionlist != null) {
        Map context = new HashMap();
        for (int i = 0; i < actionlist.size(); i++) {
          /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
            DfLogger.debug(this, m + "running plugin #" + i, null, null);
          MrcsPlugin plugin = (MrcsPlugin) actionlist.get(i);
          /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
            DfLogger.debug(this, m + "-- instantiating - " + plugin.PluginClassName, null, null);
          IMrcsWorkflowServerPlugin doit =
              (IMrcsWorkflowServerPlugin) Class.forName(plugin.PluginClassName).newInstance();
          /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
            DfLogger.debug(this, m + "-- doit!", null, null);
          doit.execute(
              sessionmgr,
              docbase,
              workitem,
              workflow,
              process,
              mrcsapp,
              plugin.PluginConfiguration,
              context);
          /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
            DfLogger.debug(this, m + "-- done!", null, null);
        }
      }

    } catch (Exception e) {
      /*-ERROR-*/ DfLogger.error(this, m + "error in promoting workitem packages...", null, e);
      sessionmgr.release(session);
      throw e;
    }

    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "completing workitem...", null, null);
    workitem.complete();

    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "releasing session", null, null);
    sessionmgr.release(session);
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "session released", null, null);
  }
  public IDfSessionManager getDBOSession() throws Exception {
    // this uses the user to get Mrcs Config to look up the DBO!
    /*-CONFIG-*/ String m = "getDBOSession - ";
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "ST Config lookup...", null, null);
    StateTransitionConfigFactory sts = StateTransitionConfigFactory.getSTConfig();

    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(
          this, m + "getting config session so we can query for the dbo's name", null, null);
    IDfSessionManager usersessionmgr = sts.cfgSession();
    IDfSession usersession = usersessionmgr.getSession(sts.cfgDocbase());
    String docbase = usersession.getDocbaseName();
    String dbo = usersession.getDocbaseOwnerName();
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "quick dbo name: " + dbo, null, null);
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "create query objects for lookup", null, null);
    String dboquery = "select r_install_owner from dm_server_config";
    IDfCollection col = null;
    IDfQuery q = new DfQuery();
    q.setDQL(dboquery);
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "executing " + dboquery, null, null);
    col = q.execute(usersession, IDfQuery.DF_READ_QUERY);
    if (col.next()) {
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "query successful, reading dbo's name", null, null);
      dbo = col.getString("r_install_owner");
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "DBO name via query: " + dbo, null, null);
      col.close();
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "releasing user session", null, null);
      usersessionmgr.release(usersession);
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "user session released", null, null);
    } else {
      col.close();
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "releasing user session", null, null);
      usersessionmgr.release(usersession);
      /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
        DfLogger.debug(this, m + "user session released", null, null);
      throw new RuntimeException("r_install_owner not retrievable from docbase");
    }

    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "creating DCTM client object", null, null);
    IDfClient client = DfClient.getLocalClient();
    IDfSessionManager sMgr = null;
    DfLoginInfo loginInfo = new DfLoginInfo();
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "setting identity to dbo user " + dbo, null, null);
    loginInfo.setUser(dbo);
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "getting DBO session", null, null);
    sMgr = client.newSessionManager();
    sMgr.setIdentity(docbase, loginInfo);
    /*-DEBUG-*/ if (DfLogger.isDebugEnabled(this))
      DfLogger.debug(this, m + "returning", null, null);
    return sMgr;
  }