public synchronized ProcessEngine installProcessArchive(ProcessArchive processArchive) {
    final String paName = processArchive.getName();

    if (!isActive) {
      throw new FoxPlatformException(
          "Cannot install process archive with name "
              + paName
              + ": ProcessEngineService is not active.");
    }

    if (installedProcessArchivesByName.containsKey(paName)) {
      throw new FoxPlatformException(
          "Cannot install process archive with name '"
              + paName
              + "': process archive with same name already installed.");
    }

    log.info("Installing process archive '" + paName + "'");
    Deployment deployment = performEngineDeployment(processArchive);

    ProcessArchiveContext processArchiveContext =
        new ProcessArchiveContext(deployment, processArchive);
    processArchiveContext.setActive(true);
    installedProcessArchivesByName.put(processArchive.getName(), processArchiveContext);

    ArrayList<ProcessArchive> processArchives =
        new ArrayList<ProcessArchive>(cachedProcessArchives);
    processArchives.add(processArchive);
    cachedProcessArchives = Collections.unmodifiableList(processArchives);

    if (deployment != null) {
      List<ProcessDefinition> processDefinitionsForThisDeployment =
          activitiProcessEngine
              .getRepositoryService()
              .createProcessDefinitionQuery()
              .deploymentId(deployment.getId())
              .list();
      for (ProcessDefinition processDefinition : processDefinitionsForThisDeployment) {
        installedProcessArchivesByProcessDefinitionKey.put(
            processDefinition.getKey(), processArchiveContext);
      }
      log.info(
          "Installed process archive '"
              + paName
              + "' to process engine '"
              + processEngineName
              + "'.");
      return activitiProcessEngine;
    } else {
      log.info(
          "Installed empty process archive '"
              + paName
              + "'. Process archive will have access to process engine with name '"
              + processEngineName
              + "'.");
      return activitiProcessEngine;
    }
  }
 public ProcessArchive getProcessArchiveByProcessDefinitionKey(String processDefinitionKey) {
   ProcessArchiveContext processArchiveContext =
       installedProcessArchivesByProcessDefinitionKey.get(processDefinitionKey);
   if (processArchiveContext == null) {
     throw new FoxPlatformException(
         "No process archive installed for key '"
             + processDefinitionKey
             + "', on process engine '"
             + processEngineName
             + "'.");
   }
   return processArchiveContext.getProcessArchive();
 }
  public synchronized void stop() {
    fireBeforeProcessEngineControllerStop(this);
    closeProcessEngine();

    Collection<ProcessArchiveContext> installedProcessArchives =
        new ArrayList<ProcessArchiveContext>(installedProcessArchivesByName.values());
    for (ProcessArchiveContext processArchive : installedProcessArchives) {
      unInstallProcessArchive(processArchive.getProcessArchive());
    }

    processEngineRegistry.processEngineUninstalled(this);

    installedProcessArchivesByName.clear();
    installedProcessArchivesByProcessDefinitionKey.clear();
    activitiProcessEngine = null;
    processEngineConfiguration = null;
    isActive = false;

    fireAfterProcessEngineControllerStop(this);
  }
  protected void performUndeployment(ProcessArchive processArchive) {
    final String paName = processArchive.getName();

    ProcessArchiveContext processArchiveContext = installedProcessArchivesByName.get(paName);
    if (processArchiveContext == null) {
      return;
    }

    try {
      processArchiveContext.setUndelploying(true);
      performEngineUndeployment(processArchive);
    } catch (Exception e) {
      log.log(Level.SEVERE, "Exception while performing process engine undeployment: ", e);
    } finally {
      processArchiveContext.setUndelploying(false);
      processArchiveContext.setActive(false);

      installedProcessArchivesByName.remove(paName);

      ArrayList<ProcessArchive> processArchives =
          new ArrayList<ProcessArchive>(cachedProcessArchives);
      processArchives.remove(processArchive);
      cachedProcessArchives = Collections.unmodifiableList(processArchives);

      if (processArchiveContext.getActivitiDeployment() != null) {
        String activitiDeploymentId = processArchiveContext.getActivitiDeployment().getId();
        List<ProcessDefinition> processDefinitions =
            activitiProcessEngine
                .getRepositoryService()
                .createProcessDefinitionQuery()
                .deploymentId(activitiDeploymentId)
                .list();
        for (ProcessDefinition processDefinition : processDefinitions) {
          installedProcessArchivesByProcessDefinitionKey.remove(processDefinition.getKey());
        }
      }
    }
  }