/**
   * 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);
      }
    }
  }
  private static void createAndDeployJar(KieServices ks, ReleaseId releaseId, String... drls) {
    KieFileSystem kfs = ks.newKieFileSystem().generateAndWritePomXML(releaseId);
    for (int i = 0; i < drls.length; i++) {
      if (drls[i] != null) {
        kfs.write("src/main/resources/org/pkg1/r" + i + ".drl", drls[i]);
      }
    }
    byte[] pom = kfs.read("pom.xml");
    KieBuilder kb = ks.newKieBuilder(kfs).buildAll();
    Assert.assertFalse(
        kb.getResults().getMessages(org.kie.api.builder.Message.Level.ERROR).toString(),
        kb.getResults().hasMessages(org.kie.api.builder.Message.Level.ERROR));
    InternalKieModule kieModule = (InternalKieModule) ks.getRepository().getKieModule(releaseId);
    byte[] jar = kieModule.getBytes();

    repository = MavenRepository.getMavenRepository();
    repository.deployArtifact(releaseId, jar, pom);
  }
  @Override
  public ClassLoader getClassLoader(KieModule kmodule) {
    ClassLoader parent = Thread.currentThread().getContextClassLoader();
    if (parent == null) {
      parent = ClassLoader.getSystemClassLoader();
    }
    if (parent == null) {
      parent = MavenClassLoaderResolver.class.getClassLoader();
    }

    InternalKieModule internalKModule = (InternalKieModule) kmodule;
    Collection<ReleaseId> jarDependencies = internalKModule.getJarDependencies();

    if (jarDependencies.isEmpty()) {
      return parent;
    }

    ArtifactResolver resolver = ArtifactResolver.getResolverFor(internalKModule.getPomModel());
    List<URL> urls = new ArrayList<URL>();
    List<ReleaseId> unresolvedDeps = new ArrayList<ReleaseId>();

    for (ReleaseId rid : jarDependencies) {
      try {
        Artifact artifact = resolver.resolveArtifact(rid);
        if (artifact != null) {
          File jar = artifact.getFile();
          urls.add(jar.toURI().toURL());
        } else {
          logger.error("Dependency artifact not found for: " + rid);
          unresolvedDeps.add(rid);
        }
      } catch (MalformedURLException e) {
        throw new RuntimeException(e);
      }
    }

    internalKModule.setUnresolvedDependencies(unresolvedDeps);
    return new URLClassLoader(urls.toArray(new URL[urls.size()]), parent);
  }
 private void addDependencies(
     InternalKieModule kieModule,
     ArtifactResolver resolver,
     List<DependencyDescriptor> dependencies) {
   for (DependencyDescriptor dep : dependencies) {
     InternalKieModule dependency =
         (InternalKieModule)
             KieServices.Factory.get().getRepository().getKieModule(dep.getReleaseId());
     if (dependency != null) {
       kieModule.addKieDependency(dependency);
     } else {
       Artifact depArtifact = resolver.resolveArtifact(dep.getReleaseId());
       if (depArtifact != null && isKJar(depArtifact.getFile())) {
         ReleaseId depReleaseId = new DependencyDescriptor(depArtifact).getReleaseId();
         ZipKieModule zipKieModule = createZipKieModule(depReleaseId, depArtifact.getFile());
         if (zipKieModule != null) {
           kieModule.addKieDependency(zipKieModule);
         }
       }
     }
   }
 }
  @Override
  public void deploy(DeploymentUnit unit) {
    try {
      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);

      // Create the release id
      KieContainer kieContainer = kmoduleUnit.getKieContainer();
      ReleaseId releaseId = null;
      if (kieContainer == null) {
        KieServices ks = KieServices.Factory.get();

        releaseId =
            ks.newReleaseId(
                kmoduleUnit.getGroupId(), kmoduleUnit.getArtifactId(), kmoduleUnit.getVersion());

        MavenRepository repository = getMavenRepository();
        repository.resolveArtifact(releaseId.toExternalForm());

        kieContainer = ks.newKieContainer(releaseId);

        kmoduleUnit.setKieContainer(kieContainer);
      }
      releaseId = kieContainer.getReleaseId();

      // retrieve the kbase name
      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, either it does not exist or there are multiple default kbases in kmodule.xml");
      }

      KieBase kbase = kieContainer.getKieBase(kbaseName);
      Map<String, ProcessDescriptor> processDescriptors = new HashMap<String, ProcessDescriptor>();
      for (org.kie.api.definition.process.Process process : kbase.getProcesses()) {
        processDescriptors.put(
            process.getId(), (ProcessDescriptor) process.getMetaData().get("ProcessDescriptor"));
      }

      // TODO: add forms data?
      Collection<String> files = module.getFileNames();

      processResources(
          module, files, kieContainer, kmoduleUnit, deployedUnit, releaseId, processDescriptors);

      // process the files in the deployment
      if (module.getKieDependencies() != null) {
        Collection<InternalKieModule> dependencies = module.getKieDependencies().values();
        for (InternalKieModule depModule : dependencies) {

          logger.debug("Processing dependency module " + depModule.getReleaseId());
          files = depModule.getFileNames();

          processResources(
              depModule,
              files,
              kieContainer,
              kmoduleUnit,
              deployedUnit,
              depModule.getReleaseId(),
              processDescriptors);
        }
      }
      Collection<ReleaseId> dependencies =
          module.getJarDependencies(new DependencyFilter.ExcludeScopeFilter("test", "provided"));

      // process deployment dependencies
      if (dependencies != null && !dependencies.isEmpty()) {
        // Classes 2: classes added from project and dependencies added
        processClassloader(kieContainer, deployedUnit);
      }

      AuditEventBuilder auditLoggerBuilder =
          setupAuditLogger(identityProvider, unit.getIdentifier());

      RuntimeEnvironmentBuilder builder =
          boostrapRuntimeEnvironmentBuilder(
                  kmoduleUnit, deployedUnit, kieContainer, kmoduleUnit.getMergeMode())
              .knowledgeBase(kbase)
              .classLoader(kieContainer.getClassLoader());

      builder.registerableItemsFactory(
          getRegisterableItemsFactory(auditLoggerBuilder, kieContainer, kmoduleUnit));

      commonDeploy(unit, deployedUnit, builder.get(), kieContainer);
      kmoduleUnit.setDeployed(true);
    } catch (Throwable e) {
      logger.warn("Unexpected error while deploying unit {}", unit.getIdentifier(), e);
      // catch all possible errors to be able to report them to caller as RuntimeException
      throw new RuntimeException(e);
    }
  }
  @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());
  }