/**
   * Goes through all files in a deployment, and processes them so that they are then ready for use
   * after deployment.
   *
   * @param module The {@link InternalKieModule}, necessary to get form content
   * @param files The {@link List} of file (names) to process.
   * @param kieContainer The {@link KieContainer}, necesary in order to load classes
   * @param deploymentUnit The {@link DeploymentUnit}, necessary to get the deployment id
   * @param deployedUnit The {@link DeployedUnit}, which contains the results of actions here
   */
  protected void processResources(
      InternalKieModule module,
      Collection<String> files,
      KieContainer kieContainer,
      DeploymentUnit unit,
      DeployedUnitImpl deployedUnit,
      ReleaseId releaseId,
      Map<String, ProcessDescriptor> processes) {
    for (String fileName : files) {
      if (fileName.matches(".+bpmn[2]?$")) {
        ProcessAssetDesc process;
        try {
          String processString = new String(module.getBytes(fileName), "UTF-8");
          String processId = getProcessId(processString);
          ProcessDescriptor processDesriptor = processes.get(processId);
          if (processDesriptor != null) {
            process = processDesriptor.getProcess();
            if (process == null) {
              throw new IllegalArgumentException("Unable to read process " + fileName);
            }
            process.setEncodedProcessSource(Base64.encodeBase64String(processString.getBytes()));
            process.setDeploymentId(unit.getIdentifier());

            deployedUnit.addAssetLocation(process.getId(), process);
            bpmn2Service.addProcessDefinition(
                unit.getIdentifier(), processId, processDesriptor, kieContainer);
          }
        } catch (UnsupportedEncodingException e) {
          throw new IllegalArgumentException(
              "Unsupported encoding while processing process " + fileName);
        }
      } else if (fileName.matches(".+ftl$")
          || fileName.matches(".+form$")
          || fileName.matches(".+frm$")) {
        try {
          String formContent = new String(module.getBytes(fileName), "UTF-8");
          if (fileName.indexOf("/") != -1)
            fileName = fileName.substring(fileName.lastIndexOf("/") + 1);
          formManagerService.registerForm(unit.getIdentifier(), fileName, formContent);
        } catch (UnsupportedEncodingException e) {
          throw new IllegalArgumentException(
              "Unsupported encoding while processing form " + fileName);
        }
      } else if (fileName.matches(".+class$")) {
        // Classes 1: classes from deployment added
        String className = fileName.replaceAll("/", ".");
        className = className.substring(0, fileName.length() - ".class".length());
        Class deploymentClass = null;
        try {
          deploymentClass = kieContainer.getClassLoader().loadClass(className);
        } catch (ClassNotFoundException cnfe) {
          throw new IllegalArgumentException("Class " + className + " not found in the project");
        } catch (NoClassDefFoundError e) {
          throw new IllegalArgumentException("Class " + className + " not found in the project");
        }
        addClassToDeployedUnit(deploymentClass, deployedUnit);
      }
    }
  }
  public void commonDeploy(
      DeploymentUnit unit,
      DeployedUnitImpl deployedUnit,
      RuntimeEnvironment environemnt,
      KieContainer kieContainer) {

    synchronized (this) {
      if (deploymentsMap.containsKey(unit.getIdentifier())) {
        DeployedUnit deployed = deploymentsMap.remove(unit.getIdentifier());
        RuntimeManager manager = deployed.getRuntimeManager();
        manager.close();
      }
      RuntimeManager manager = null;
      deploymentsMap.put(unit.getIdentifier(), deployedUnit);
      ((SimpleRuntimeEnvironment) environemnt)
          .addToEnvironment("IdentityProvider", identityProvider);
      try {
        switch (unit.getStrategy()) {
          case SINGLETON:
            manager = managerFactory.newSingletonRuntimeManager(environemnt, unit.getIdentifier());
            break;
          case PER_REQUEST:
            manager = managerFactory.newPerRequestRuntimeManager(environemnt, unit.getIdentifier());
            break;

          case PER_PROCESS_INSTANCE:
            manager =
                managerFactory.newPerProcessInstanceRuntimeManager(
                    environemnt, unit.getIdentifier());
            break;
          default:
            throw new IllegalArgumentException("Invalid strategy " + unit.getStrategy());
        }
        ((InternalRuntimeManager) manager).setKieContainer(kieContainer);
        deployedUnit.setRuntimeManager(manager);
        DeploymentDescriptor descriptor =
            ((InternalRuntimeManager) manager).getDeploymentDescriptor();
        List<String> requiredRoles = descriptor.getRequiredRoles(DeploymentDescriptor.TYPE_EXECUTE);
        if (requiredRoles != null && !requiredRoles.isEmpty()) {
          ((InternalRuntimeManager) manager)
              .setSecurityManager(
                  new IdentityRolesSecurityManager(identityProvider, requiredRoles));
        }
        notifyOnDeploy(unit, deployedUnit);

      } catch (Throwable e) {
        deploymentsMap.remove(unit.getIdentifier());
        if (manager != null) {
          manager.close();
        }
        notifyOnUnDeploy(unit, deployedUnit);
        throw new RuntimeException(e);
      }
    }
  }
  @Override
  public void deactivate(String deploymentId) {
    DeployedUnit deployed = getDeployedUnit(deploymentId);
    if (deployed != null) {
      ((DeployedUnitImpl) deployed).setActive(false);

      ((InternalRuntimeManager) deployed.getRuntimeManager()).deactivate();

      notifyOnDeactivate(deployed.getDeploymentUnit(), deployed);
    }
  }
 private void addClassToDeployedUnit(Class deploymentClass, DeployedUnitImpl deployedUnit) {
   if (deploymentClass != null) {
     DeploymentUnit unit = deployedUnit.getDeploymentUnit();
     Boolean limitClasses = false;
     if (unit != null) {
       DeploymentDescriptor depDesc = ((KModuleDeploymentUnit) unit).getDeploymentDescriptor();
       if (depDesc != null) {
         limitClasses = depDesc.getLimitSerializationClasses();
       }
     }
     if (limitClasses != null && limitClasses) {
       filterClassesAddedToDeployedUnit(deployedUnit, deploymentClass);
     } else {
       logger.debug(
           "Loaded {} onto the classpath from deployment {}",
           deploymentClass.getName(),
           unit.getIdentifier());
       deployedUnit.addClass(deploymentClass);
     }
   }
 }
  /**
   * This method is used to filter classes that are added to the {@link DeployedUnit}. When this
   * method is used, only classes that are meant to be used with serialization are added to the
   * deployment. This feature can be used to, for example, make sure that
   * non-serialization-compatible classes (such as interfaces), do not complicate the use of a
   * deployment with the remote services (REST/JMS/WS). Note to other developers, it's possible that
   * classpath problems may arise, because of either classloader or lazy class resolution problems:
   * I simply don't know enough about the inner workings of the JAXB implementations (plural!) to
   * figure this out.
   *
   * @param deployedUnit The {@link DeployedUnit} to which the classes are added. The {@link
   *     DeployedUnit} to which the classes are added. The {@link DeployedUnit} to which the classes
   *     are added.
   * @param classToAdd The class to add to the {@link DeployedUnit}.
   */
  private static void filterClassesAddedToDeployedUnit(
      DeployedUnit deployedUnit, Class classToAdd) {

    if (classToAdd.isInterface()
        || classToAdd.isAnnotation()
        || classToAdd.isLocalClass()
        || classToAdd.isMemberClass()) {
      return;
    }

    boolean jaxbClass = false;
    boolean remoteableClass = false;
    // @XmlRootElement and @XmlType may be used with inheritance
    for (Annotation anno : classToAdd.getAnnotations()) {
      if (XmlRootElement.class.equals(anno.annotationType())) {
        jaxbClass = true;
        break;
      }
      if (XmlType.class.equals(anno.annotationType())) {
        jaxbClass = true;
        break;
      }
    }
    // @Remotable is not inheritable, and may not be used as such
    for (Annotation anno : classToAdd.getDeclaredAnnotations()) {
      if (Remotable.class.equals(anno.annotationType())) {
        remoteableClass = true;
        break;
      }
    }

    if (jaxbClass || remoteableClass) {
      DeployedUnitImpl deployedUnitImpl = (DeployedUnitImpl) deployedUnit;
      deployedUnitImpl.addClass(classToAdd);
    }
  }
  @Override
  public void deploy(DeploymentUnit unit) {
    super.deploy(unit);
    if (!(unit instanceof KModuleDeploymentUnit)) {
      throw new IllegalArgumentException(
          "Invalid deployment unit provided - " + unit.getClass().getName());
    }
    KModuleDeploymentUnit kmoduleUnit = (KModuleDeploymentUnit) unit;
    DeployedUnitImpl deployedUnit = new DeployedUnitImpl(unit);
    KieServices ks = KieServices.Factory.get();
    MavenRepository repository = getMavenRepository();
    repository.resolveArtifact(kmoduleUnit.getIdentifier());

    ReleaseId releaseId =
        ks.newReleaseId(
            kmoduleUnit.getGroupId(), kmoduleUnit.getArtifactId(), kmoduleUnit.getVersion());
    KieContainer kieContainer = ks.newKieContainer(releaseId);

    String kbaseName = kmoduleUnit.getKbaseName();
    if (StringUtils.isEmpty(kbaseName)) {
      KieBaseModel defaultKBaseModel =
          ((KieContainerImpl) kieContainer).getKieProject().getDefaultKieBaseModel();
      if (defaultKBaseModel != null) {
        kbaseName = defaultKBaseModel.getName();
      } else {
        kbaseName = DEFAULT_KBASE_NAME;
      }
    }
    InternalKieModule module =
        (InternalKieModule) ((KieContainerImpl) kieContainer).getKieModuleForKBase(kbaseName);
    if (module == null) {
      throw new IllegalStateException("Cannot find kbase with name " + kbaseName);
    }

    Map<String, String> formsData = new HashMap<String, String>();
    Collection<String> files = module.getFileNames();
    for (String fileName : files) {
      if (fileName.matches(".+bpmn[2]?$")) {
        ProcessDesc process;
        try {
          String processString = new String(module.getBytes(fileName), "UTF-8");
          process = bpmn2Service.findProcessId(processString, kieContainer.getClassLoader());
          process.setEncodedProcessSource(Base64.encodeBase64String(processString.getBytes()));
          process.setDeploymentId(unit.getIdentifier());
          process.setForms(formsData);
          deployedUnit.addAssetLocation(process.getId(), process);
        } catch (UnsupportedEncodingException e) {
          logger.warn("Unable to load content for file '{}' : {}", fileName, e);
        }
      } else if (fileName.matches(".+ftl$")) {
        try {
          String formContent = new String(module.getBytes(fileName), "UTF-8");
          Pattern regex = Pattern.compile("(.{0}|.*/)([^/]*?)\\.ftl");
          Matcher m = regex.matcher(fileName);
          String key = fileName;
          while (m.find()) {
            key = m.group(2);
          }
          formsData.put(key, formContent);
        } catch (UnsupportedEncodingException e) {
          logger.warn("Unable to load content for form '{}' : {}", fileName, e);
        }
      } else if (fileName.matches(".+form$")) {
        try {
          String formContent = new String(module.getBytes(fileName), "UTF-8");
          Pattern regex = Pattern.compile("(.{0}|.*/)([^/]*?)\\.form");
          Matcher m = regex.matcher(fileName);
          String key = fileName;
          while (m.find()) {
            key = m.group(2);
          }
          formsData.put(key + ".form", formContent);
        } catch (UnsupportedEncodingException e) {
          logger.warn("Unable to load content for form '{}' : {}", fileName, e);
        }
      }
    }

    KieBase kbase = kieContainer.getKieBase(kbaseName);

    AbstractAuditLogger auditLogger = getAuditLogger();
    ServicesAwareAuditEventBuilder auditEventBuilder = new ServicesAwareAuditEventBuilder();
    auditEventBuilder.setIdentityProvider(identityProvider);
    auditEventBuilder.setDeploymentUnitId(unit.getIdentifier());
    auditLogger.setBuilder(auditEventBuilder);

    RuntimeEnvironmentBuilder builder =
        RuntimeEnvironmentBuilder.getDefault()
            .entityManagerFactory(getEmf())
            .knowledgeBase(kbase)
            .classLoader(kieContainer.getClassLoader());
    if (beanManager != null) {
      builder.registerableItemsFactory(
          InjectableRegisterableItemsFactory.getFactory(
              beanManager, auditLogger, kieContainer, kmoduleUnit.getKsessionName()));
    }
    commonDeploy(unit, deployedUnit, builder.get());
  }