/** Find Pooled Task Instances */
  @SuppressWarnings("rawtypes")
  public static List<TaskInstance> findPooledTaskInstances(String user) throws WorkflowException {
    log.debug("findPooledTaskInstances({})", user);
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();
    ArrayList<TaskInstance> al = new ArrayList<TaskInstance>();

    try {
      TaskMgmtSession taskMgmtSession = jbpmContext.getTaskMgmtSession();

      for (Iterator it = taskMgmtSession.findPooledTaskInstances(user).iterator(); it.hasNext(); ) {
        org.jbpm.taskmgmt.exe.TaskInstance ti = (org.jbpm.taskmgmt.exe.TaskInstance) it.next();
        al.add(WorkflowUtils.copy(ti));
      }

      // Sort
      Collections.sort(al);
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("findPooledTaskInstances: {}", al);
    return al;
  }
  /** Find Task Instances */
  @SuppressWarnings("rawtypes")
  public static List<TaskInstance> findTaskInstances(long processInstanceId)
      throws WorkflowException {
    log.debug("findTaskInstances({})", processInstanceId);
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();
    ArrayList<TaskInstance> al = new ArrayList<TaskInstance>();

    try {
      GraphSession graphSession = jbpmContext.getGraphSession();
      org.jbpm.graph.exe.ProcessInstance pi = graphSession.getProcessInstance(processInstanceId);
      TaskMgmtInstance taskMgmtInstance = pi.getTaskMgmtInstance();

      if (taskMgmtInstance.getTaskInstances() != null) {
        for (Iterator it = taskMgmtInstance.getTaskInstances().iterator(); it.hasNext(); ) {
          org.jbpm.taskmgmt.exe.TaskInstance ti = (org.jbpm.taskmgmt.exe.TaskInstance) it.next();
          al.add(WorkflowUtils.copy(ti));
        }
      }

      // Sort
      Collections.sort(al);
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("findTaskInstances: {}", al);
    return al;
  }
  /** Find All Process Definition Versions */
  @SuppressWarnings("rawtypes")
  public static List<ProcessDefinition> findAllProcessDefinitionVersions(String name)
      throws WorkflowException {
    log.debug("findAllProcessDefinitionVersions({})", name);
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();
    List<ProcessDefinition> al = new ArrayList<ProcessDefinition>();

    try {
      GraphSession graphSession = jbpmContext.getGraphSession();

      for (Iterator it = graphSession.findAllProcessDefinitionVersions(name).iterator();
          it.hasNext(); ) {
        org.jbpm.graph.def.ProcessDefinition procDef =
            (org.jbpm.graph.def.ProcessDefinition) it.next();
        al.add(WorkflowUtils.copy(procDef));
      }
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("findAllProcessDefinitionVersions: {}", al);
    return al;
  }
  /** Send Token Signal */
  public static Token sendTokenSignal(long tokenId, String transitionName)
      throws WorkflowException {
    log.debug("sendTokenSignal({}, {})", new Object[] {tokenId, transitionName});
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();
    Token vo = new Token();

    try {
      org.jbpm.graph.exe.Token t = jbpmContext.getToken(tokenId);

      if (transitionName != null && !transitionName.equals("")) {
        t.signal(transitionName);
      } else {
        t.signal();
      }

      jbpmContext.getSession().flush();
      vo = WorkflowUtils.copy(t);

      // Avoid recursion
      vo.setProcessInstance(WorkflowUtils.copy(t.getProcessInstance()));
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("sendTokenSignal: {}", vo);
    return vo;
  }
  /** Find Process Instance */
  @SuppressWarnings("rawtypes")
  public static List<ProcessInstance> findProcessInstances(long processDefinitionId)
      throws WorkflowException {
    log.debug("findProcessInstances({})", processDefinitionId);
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();
    List<ProcessInstance> al = new ArrayList<ProcessInstance>();

    try {
      GraphSession graphSession = jbpmContext.getGraphSession();

      for (Iterator it = graphSession.findProcessInstances(processDefinitionId).iterator();
          it.hasNext(); ) {
        org.jbpm.graph.exe.ProcessInstance procInst =
            (org.jbpm.graph.exe.ProcessInstance) it.next();
        al.add(WorkflowUtils.copy(procInst));
      }
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("findProcessInstances: {}", al);
    return al;
  }
  @SuppressWarnings("rawtypes")
  public static ProcessDefinition findLastProcessDefinition(String name) throws WorkflowException {
    log.debug("findLastProcessDefinition()");
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();
    ProcessDefinition pd = new ProcessDefinition();

    try {
      GraphSession graphSession = jbpmContext.getGraphSession();

      for (Iterator it = graphSession.findLatestProcessDefinitions().iterator(); it.hasNext(); ) {
        org.jbpm.graph.def.ProcessDefinition procDef =
            (org.jbpm.graph.def.ProcessDefinition) it.next();

        if (procDef.getName().equals(name)) {
          pd = WorkflowUtils.copy(procDef);
        }
      }
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("findLastProcessDefinition: {}", pd);
    return pd;
  }
  /** Send Process Instance Signal */
  public static ProcessInstance sendProcessInstanceSignal(
      long processInstanceId, String transitionName) throws WorkflowException {
    log.debug(
        "sendProcessInstanceSignal({}, {})", new Object[] {processInstanceId, transitionName});
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();
    ProcessInstance vo = new ProcessInstance();

    try {
      GraphSession graphSession = jbpmContext.getGraphSession();
      org.jbpm.graph.exe.ProcessInstance pi = graphSession.getProcessInstance(processInstanceId);
      org.jbpm.graph.exe.Token t = pi.getRootToken();

      if (transitionName != null && !transitionName.equals("")) {
        t.signal(transitionName);
      } else {
        t.signal();
      }

      jbpmContext.getSession().flush();
      vo = WorkflowUtils.copy(pi);
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("sendProcessInstanceSignal: {}", vo);
    return vo;
  }
  /** End Task Instance */
  public static void endTaskInstance(long taskInstanceId, String transitionName)
      throws WorkflowException {
    log.debug("endTaskInstance({}, {})", new Object[] {taskInstanceId, transitionName});
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();

    try {
      TaskMgmtSession taskMgmtSession = jbpmContext.getTaskMgmtSession();
      org.jbpm.taskmgmt.exe.TaskInstance ti = taskMgmtSession.getTaskInstance(taskInstanceId);

      if (transitionName != null && !transitionName.equals("")) {
        if (ti.getStart() == null) {
          ti.start();
        }

        ti.end(transitionName);
      } else {
        if (ti.getStart() == null) {
          ti.start();
        }

        ti.end();
      }

      jbpmContext.getSession().flush();
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("endTaskInstance: void");
  }
  /** Register Process Definition */
  public static void registerProcessDefinition(InputStream is)
      throws WorkflowException, ParseException, IOException {
    log.debug("registerProcessDefinition({})", is);
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();
    InputStream isForms = null;
    ZipInputStream zis = null;

    if (Config.SYSTEM_READONLY) {
      throw new WorkflowException("System is in read-only mode");
    }

    try {
      zis = new ZipInputStream(is);
      org.jbpm.graph.def.ProcessDefinition processDefinition =
          org.jbpm.graph.def.ProcessDefinition.parseParZipInputStream(zis);

      // Check xml form definition
      FileDefinition fileDef = processDefinition.getFileDefinition();
      isForms = fileDef.getInputStream("forms.xml");
      FormUtils.parseWorkflowForms(isForms);

      // If it is ok, deploy it
      jbpmContext.deployProcessDefinition(processDefinition);
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      IOUtils.closeQuietly(isForms);
      IOUtils.closeQuietly(zis);
      jbpmContext.close();
    }

    log.debug("registerProcessDefinition: void");
  }
  /** Start Process Definition */
  public static ProcessInstance runProcessDefinition(
      String user, long processDefinitionId, String uuid, List<FormElement> variables)
      throws WorkflowException {
    log.debug(
        "runProcessDefinition({}, {}, {}, {})",
        new Object[] {user, processDefinitionId, uuid, variables});
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();
    ProcessInstance vo = new ProcessInstance();

    if (Config.SYSTEM_READONLY) {
      throw new WorkflowException("System is in read-only mode");
    }

    try {
      jbpmContext.setActorId(user);
      GraphSession graphSession = jbpmContext.getGraphSession();
      Map<String, Object> hm = new HashMap<String, Object>();
      hm.put(Config.WORKFLOW_PROCESS_INSTANCE_VARIABLE_UUID, uuid);

      for (FormElement fe : variables) {
        hm.put(fe.getName(), fe);
      }

      org.jbpm.graph.def.ProcessDefinition pd =
          graphSession.getProcessDefinition(processDefinitionId);
      org.jbpm.graph.exe.ProcessInstance pi = pd.createProcessInstance(hm);

      if (pi != null) {
        org.jbpm.taskmgmt.exe.TaskMgmtInstance tmi = pi.getTaskMgmtInstance();

        // http://community.jboss.org/thread/115182
        if (tmi.getTaskMgmtDefinition().getStartTask() != null) {
          org.jbpm.taskmgmt.exe.TaskInstance ti = tmi.createStartTaskInstance();

          if (Config.WORKFLOW_START_TASK_AUTO_RUN) {
            ti.start();
            ti.end();
          }
        } else {
          pi.getRootToken().signal();
        }

        jbpmContext.save(pi);
        vo = WorkflowUtils.copy(pi);
      }
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("runProcessDefinition: {}", vo);
    return vo;
  }
  /** Resume Process Instance */
  public static void resumeProcessInstance(long processInstanceId) throws WorkflowException {
    log.debug("resumeProcessInstance({})", processInstanceId);
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();

    try {
      org.jbpm.graph.exe.ProcessInstance pi = jbpmContext.getProcessInstance(processInstanceId);
      pi.resume();
      jbpmContext.getSession().flush();
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }
  }
  /** Delete Process Instance */
  public static void deleteProcessInstance(long processInstanceId) throws WorkflowException {
    log.debug("deleteProcessInstance({})", processInstanceId);
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();

    try {
      GraphSession graphSession = jbpmContext.getGraphSession();
      graphSession.deleteProcessInstance(processInstanceId);
      jbpmContext.getSession().flush();
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }
  }
  /** Delete Process Instance */
  public static void deleteProcessInstanceVariable(long processInstanceId, String name)
      throws WorkflowException {
    log.debug("deleteProcessInstanceVariable({}, {})", new Object[] {processInstanceId, name});
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();

    try {
      org.jbpm.graph.exe.ProcessInstance pi = jbpmContext.getProcessInstance(processInstanceId);
      pi.getContextInstance().deleteVariable(name);
      jbpmContext.getSession().flush();
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }
  }
  /** End Token */
  public static void endToken(long tokenId) throws WorkflowException {
    log.debug("endToken({})", tokenId);
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();

    try {
      jbpmContext.getToken(tokenId).end();
      jbpmContext.getSession().flush();
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("endToken: void");
  }
  /** Add Task Instance Comment */
  public static void addTaskInstanceComment(String user, long taskInstanceId, String message)
      throws WorkflowException {
    log.debug("addTaskInstanceComment({}, {}, {})", new Object[] {user, taskInstanceId, message});
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();

    try {
      TaskMgmtSession taskMgmtSession = jbpmContext.getTaskMgmtSession();
      org.jbpm.taskmgmt.exe.TaskInstance ti = taskMgmtSession.getTaskInstance(taskInstanceId);
      ti.addComment(new org.jbpm.graph.exe.Comment(user, message));
      jbpmContext.getSession().flush();
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }
  }
  /** Add Token Comment */
  public static void addTokenComment(String user, long tokenId, String message)
      throws WorkflowException {
    log.debug("addTokenComment({}, {}, {})", new Object[] {user, tokenId, message});
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();

    try {
      org.jbpm.graph.exe.Token t = jbpmContext.getToken(tokenId);
      t.addComment(new org.jbpm.graph.exe.Comment(user, message));
      jbpmContext.getSession().flush();
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("addTokenComment: void");
  }
  /** Resume Task Instance */
  public static void resumeTaskInstance(long taskInstanceId) throws WorkflowException {
    log.debug("resumeTaskInstance({})", taskInstanceId);
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();

    try {
      TaskMgmtSession taskMgmtSession = jbpmContext.getTaskMgmtSession();
      org.jbpm.taskmgmt.exe.TaskInstance ti = taskMgmtSession.getTaskInstance(taskInstanceId);
      ti.resume();
      jbpmContext.getSession().flush();
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("resumeTaskInstance: void");
  }
  /** Delete Task Instance Variable */
  public static void deleteTaskInstanceVariable(long taskInstanceId, String name)
      throws WorkflowException {
    log.debug("deleteTaskInstanceVariable({}, {})", new Object[] {taskInstanceId, name});
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();

    try {
      org.jbpm.taskmgmt.exe.TaskInstance ti = jbpmContext.getTaskInstance(taskInstanceId);
      ti.deleteVariable(name);
      jbpmContext.getSession().flush();
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("deleteTaskInstanceVariable: void");
  }
  /** Set Task Instance Actor Id */
  public static void setTaskInstanceActorId(long taskInstanceId, String actorId)
      throws WorkflowException {
    log.debug("setTaskInstanceActorId({}, {})", new Object[] {taskInstanceId, actorId});
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();

    try {
      org.jbpm.taskmgmt.exe.TaskInstance ti = jbpmContext.getTaskInstance(taskInstanceId);
      ti.setActorId(actorId);
      jbpmContext.getSession().flush();
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("setTaskInstanceActorId: void");
  }
  /** Set Token Node */
  public static void setTokenNode(long tokenId, String nodeName) throws WorkflowException {
    log.debug("setTokenNode({}, {})", new Object[] {tokenId, nodeName});
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();

    try {
      org.jbpm.graph.exe.Token t = jbpmContext.getToken(tokenId);
      org.jbpm.graph.def.Node node =
          t.getProcessInstance().getProcessDefinition().getNode(nodeName);
      t.setNode(node);
      jbpmContext.getSession().flush();
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("setTokenNode: void");
  }
  /** Get Task Instance */
  public static TaskInstance getTaskInstance(long taskInstanceId) throws WorkflowException {
    log.debug("getTaskInstance({})", taskInstanceId);
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();
    TaskInstance vo = new TaskInstance();

    try {
      TaskMgmtSession taskMgmtSession = jbpmContext.getTaskMgmtSession();
      org.jbpm.taskmgmt.exe.TaskInstance ti = taskMgmtSession.getTaskInstance(taskInstanceId);
      vo = WorkflowUtils.copy(ti);
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("getTaskInstance: {}", vo);
    return vo;
  }
  /** Get Process Instance */
  public static ProcessInstance getProcessInstance(long processInstanceId)
      throws WorkflowException {
    log.debug("getProcessInstance({})", processInstanceId);
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();
    ProcessInstance vo = new ProcessInstance();

    try {
      GraphSession graphSession = jbpmContext.getGraphSession();
      org.jbpm.graph.exe.ProcessInstance pi = graphSession.getProcessInstance(processInstanceId);
      vo = WorkflowUtils.copy(pi);
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("getProcessInstance: {}", vo);
    return vo;
  }
  /** Delete Process Definition */
  public static void deleteProcessDefinition(long processDefinitionId) throws WorkflowException {
    log.debug("deleteProcessDefinition({})", processDefinitionId);
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();

    if (Config.SYSTEM_READONLY) {
      throw new WorkflowException("System is in read-only mode");
    }

    try {
      GraphSession graphSession = jbpmContext.getGraphSession();
      graphSession.deleteProcessDefinition(processDefinitionId);
      jbpmContext.getSession().flush();
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("deleteProcessDefinition: void");
  }
  /** Get Token */
  public static Token getToken(long tokenId) throws WorkflowException {
    log.debug("getToken({})", tokenId);
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();
    Token vo = new Token();

    try {
      org.jbpm.graph.exe.Token t = jbpmContext.getToken(tokenId);
      vo = WorkflowUtils.copy(t);

      // Avoid recursion
      vo.setProcessInstance(WorkflowUtils.copy(t.getProcessInstance()));
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("getToken: " + vo);
    return vo;
  }
  /** Set Task Instance Values */
  public static void setTaskInstanceValues(
      long taskInstanceId, String transitionName, List<FormElement> values)
      throws WorkflowException {
    log.debug(
        "setTaskInstanceValues({}, {}, {})", new Object[] {taskInstanceId, transitionName, values});
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();

    try {
      TaskMgmtSession taskMgmtSession = jbpmContext.getTaskMgmtSession();
      Map<String, FormElement> hm = new HashMap<String, FormElement>();

      for (FormElement fe : values) {
        hm.put(fe.getName(), fe);
      }

      org.jbpm.taskmgmt.exe.TaskInstance ti = taskMgmtSession.getTaskInstance(taskInstanceId);
      ti.setVariables(hm);

      if (transitionName != null && !transitionName.equals("")) {
        if (ti.getStart() == null) {
          ti.start();
        }

        ti.end(transitionName);
      } else {
        if (ti.getStart() == null) {
          ti.start();
        }

        ti.end();
      }

      jbpmContext.save(ti);
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }
  }
  /** Get Process Definition Image */
  public static byte[] getProcessDefinitionImage(long processDefinitionId, String node)
      throws WorkflowException {
    log.debug("getProcessDefinitionImage({}, {})", new Object[] {processDefinitionId, node});
    JbpmContext jbpmContext = JBPMUtils.getConfig().createJbpmContext();
    byte[] image = null;

    try {
      GraphSession graphSession = jbpmContext.getGraphSession();
      org.jbpm.graph.def.ProcessDefinition pd =
          graphSession.getProcessDefinition(processDefinitionId);
      FileDefinition fileDef = pd.getFileDefinition();

      WorkflowUtils.DiagramInfo dInfo =
          WorkflowUtils.getDiagramInfo(fileDef.getInputStream("gpd.xml"));
      WorkflowUtils.DiagramNodeInfo dNodeInfo = dInfo.getNodeMap().get(node);
      BufferedImage img = ImageIO.read(fileDef.getInputStream("processimage.jpg"));

      // Obtain all nodes Y and X
      List<Integer> ordenadas = new ArrayList<Integer>();
      List<Integer> abcisas = new ArrayList<Integer>();

      for (WorkflowUtils.DiagramNodeInfo nodeInfo : dInfo.getNodeMap().values()) {
        ordenadas.add(nodeInfo.getY());
        abcisas.add(nodeInfo.getX());
      }

      // Calculate minimal Y
      Collections.sort(ordenadas);
      int fixOrd = ordenadas.get(0) < 0 ? ordenadas.get(0) : 0;

      // Calculate minimal X
      Collections.sort(abcisas);
      int fixAbs = abcisas.get(0) < 0 ? abcisas.get(0) : 0;

      if (dNodeInfo != null) {
        // Select node
        log.debug("DiagramNodeInfo: {}", dNodeInfo);
        Graphics g = img.getGraphics();
        Graphics2D g2d = (Graphics2D) g;
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.25F));
        g2d.setColor(Color.blue);
        g2d.fillRect(
            dNodeInfo.getX() - fixAbs,
            dNodeInfo.getY() - fixOrd,
            dNodeInfo.getWidth(),
            dNodeInfo.getHeight());
        g.dispose();
      }

      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ImageIO.write(img, "jpg", baos);
      image = baos.toByteArray();
      baos.flush();
      baos.close();
    } catch (JbpmException e) {
      throw new WorkflowException(e.getMessage(), e);
    } catch (IOException e) {
      throw new WorkflowException(e.getMessage(), e);
    } finally {
      jbpmContext.close();
    }

    log.debug("getProcessDefinitionImage: {}", image);
    return image;
  }