package betsy.bpmn.engines.jbpm; import java.nio.file.Files; import java.nio.file.Path; import java.time.LocalDate; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.xml.namespace.QName; import betsy.bpmn.engines.AbstractBPMNEngine; import betsy.bpmn.engines.BPMNProcessInstanceOutcomeChecker; import betsy.bpmn.engines.BPMNProcessStarter; import betsy.bpmn.engines.BPMNTestcaseMerger; import betsy.bpmn.engines.BPMNTester; import betsy.bpmn.engines.GenericBPMNTester; import betsy.bpmn.model.BPMNProcess; import betsy.bpmn.model.BPMNTestBuilder; import betsy.common.config.Configuration; import betsy.common.model.engine.EngineExtended; import betsy.common.tasks.ConsoleTasks; import betsy.common.tasks.FileTasks; import betsy.common.tasks.URLTasks; import betsy.common.tasks.WaitTasks; import betsy.common.tasks.XSLTTasks; import betsy.common.tasks.ZipTasks; import betsy.common.timeouts.timeout.TimeoutRepository; import betsy.common.util.ClasspathHelper; import org.apache.log4j.Logger; import pebl.ProcessLanguage; import pebl.benchmark.test.TestCase; public class JbpmEngine extends AbstractBPMNEngine { private static final Logger LOGGER = Logger.getLogger(JbpmEngine.class); @Override public Path getXsltPath() { return ClasspathHelper.getFilesystemPathFromClasspathPath("/bpmn/jbpm"); } @Override public EngineExtended getEngineObject() { return new EngineExtended(ProcessLanguage.BPMN, "jbpm", "6.0.1", LocalDate.of(2014, 5, 14), "Apache-2.0"); } public Path getJbpmInstallerPath() { return getServerPath().resolve("jbpm-installer"); } public String getJbpmnUrl() { return "http://localhost:8080/jbpm-console"; } public String getJbossName() { return "jboss-as-7.1.1.Final"; } public Path getJbossStandaloneDir() { return getJbpmInstallerPath().resolve(getJbossName()).resolve("standalone"); } public Path getAntPath() { return Configuration.getAntHome().resolve("bin"); } @Override public void deploy(String name, Path path) { // maven deployment for pushing it to the local maven repository (jbpm-console will fetch it from there) final Path mvnPath = Configuration.getMavenHome().resolve("bin"); Path installPath = path.getParent().resolve("install"); ZipTasks.unzip(path, installPath); ConsoleTasks.executeOnWindowsAndIgnoreError(ConsoleTasks.CliCommand.build(installPath, mvnPath.toAbsolutePath() + "/mvn -q clean install")); ConsoleTasks.setupMvn(mvnPath); ConsoleTasks.executeOnUnixAndIgnoreError(ConsoleTasks.CliCommand.build(installPath, mvnPath.toAbsolutePath() + "/mvn").values("-q", "clean", "install")); //wait for maven to deploy WaitTasks.sleep(TimeoutRepository.getTimeout("Jbpm.deploy.maven").getTimeoutInMs()); String deploymentId = getDeploymentId(name); JbpmDeployer deployer = new JbpmDeployer(getJbpmnUrl(), deploymentId); deployer.deploy(); TimeoutRepository.getTimeout("Jbpm.deploy").waitFor(deployer::isDeploymentFinished); } @Override public Path buildArchives(final BPMNProcess process) { XSLTTasks.transform(getXsltPath().resolve("../scriptTask.xsl"), process.getProcess(), process.getTargetPath().resolve("project/src/main/resources/" + process.getName() + ".bpmn2-temp"), "processName", process.getName()); XSLTTasks.transform(getXsltPath().resolve("jbpm.xsl"), process.getTargetPath().resolve("project/src/main/resources/" + process.getName() + ".bpmn2-temp"), process.getTargetPath().resolve("project/src/main/resources/" + process.getName() + ".bpmn2")); FileTasks.deleteFile(process.getTargetPath().resolve("war/WEB-INF/classes/" + process.getName() + ".bpmn2-temp")); JbpmResourcesGenerator generator = new JbpmResourcesGenerator(); generator.setJbpmSrcDir(ClasspathHelper.getFilesystemPathFromClasspathPath("/bpmn/jbpm")); generator.setDestDir(process.getTargetPath().resolve("project")); generator.setProcessName(process.getName()); generator.setGroupId("de.uniba.dsg"); generator.setVersion("1.0"); generator.generateProject(); Path zipFile = process.getTargetPackagePath().resolve(process.getName() + ".zip"); ZipTasks.zipFolder(zipFile, process.getTargetPath().resolve("project")); return zipFile; } @Override public String getEndpointUrl(String name) { return "http://localhost:8080/jbpm-console/"; } @Override public List<Path> getLogs() { List<Path> result = new LinkedList<>(); result.addAll(FileTasks.findAllInFolder(getJbossLogDir())); result.addAll(FileTasks.findAllInFolder(getJbpmInstallerPath(), "log*.txt")); return result; } @Override public void install() { JbpmInstaller installer = new JbpmInstaller(); installer.setDestinationDir(getServerPath()); installer.install(); } @Override public void startup() { Path pathToJava7 = Configuration.getJava7Home(); FileTasks.replaceTokenInFile(getJbpmInstallerPath().resolve("build.xml"),"<env key=\"JAVA_OPTS\" value=\"-XX:MaxPermSize=256m -Xms256m -Xmx512m\" />", "<env key=\"JAVA_OPTS\" value=\"-XX:MaxPermSize=256m -Xms512m -Xmx2048m -XX:-UseGCOverheadLimit\" />"); ConsoleTasks.setupAnt(getAntPath()); Map<String, String> map = new LinkedHashMap<>(1); map.put("JAVA_HOME", pathToJava7.toString()); ConsoleTasks.executeOnWindowsAndIgnoreError(ConsoleTasks.CliCommand.build(getJbpmInstallerPath(), getAntPath().toAbsolutePath() + "/ant -q start.demo.noeclipse"), map); Map<String, String> map1 = new LinkedHashMap<>(1); map1.put("JAVA_HOME", pathToJava7.toString()); ConsoleTasks.executeOnUnixAndIgnoreError(ConsoleTasks.CliCommand.build(getJbpmInstallerPath(), getAntPath().toAbsolutePath() + "/ant").values("-q", "start.demo.noeclipse"), map1); //waiting for jbpm-console for deployment and instantiating TimeoutRepository.getTimeout("Jbpm.startup").waitForSubstringInFile(getServerLog(), "JBAS018559: Deployed \"jbpm-console.war\""); } public Path getLogFileForShutdownAnalysis() { return getJbossBootLog(); } protected Path getServerLog() { return getJbossLogDir().resolve("server.log"); } private Path getJbossLogDir() { return getJbossStandaloneDir().resolve("log"); } @Override public void shutdown() { Path jbpmInstallerPath = getJbpmInstallerPath(); if (!Files.exists(jbpmInstallerPath)) { // if it is not installed, we cannot shutdown return; } ConsoleTasks.setupAnt(getAntPath()); ConsoleTasks.executeOnWindowsAndIgnoreError(ConsoleTasks.CliCommand.build(jbpmInstallerPath, getAntPath().toAbsolutePath() + "/ant -q stop.demo")); ConsoleTasks.executeOnUnixAndIgnoreError(ConsoleTasks.CliCommand.build(jbpmInstallerPath, getAntPath().toAbsolutePath() + "/ant").values("-q", "stop.demo")); if (FileTasks.hasNoFile(getLogFileForShutdownAnalysis())) { LOGGER.info("Could not shutdown, because " + getLogFileForShutdownAnalysis() + " does not exist. this indicates that the engine was never started"); return; } try { //waiting for shutdown completion using log files; e.g. "12:42:36,345 INFO [org.jboss.as] JBAS015950: JBoss AS 7.1.1.Final "Brontes" stopped in 31957ms" TimeoutRepository.getTimeout("Jbpm.shutdown").waitForSubstringInFile(getLogFileForShutdownAnalysis(), "JBAS015950"); // clean up data (with db and config files in the users home directory) ConsoleTasks.executeOnWindowsAndIgnoreError(ConsoleTasks.CliCommand.build(jbpmInstallerPath, getAntPath().toAbsolutePath() + "/ant -q clean.demo")); ConsoleTasks.executeOnUnixAndIgnoreError(ConsoleTasks.CliCommand.build(jbpmInstallerPath, getAntPath().toAbsolutePath() + "/ant").values("-q").values("clean.demo")); } catch (IllegalStateException ex) { //swallow } } protected Path getJbossBootLog() { return getJbossLogDir().resolve("boot.log"); } @Override public boolean isRunning() { return URLTasks.isUrlAvailable(getJbpmnUrl()); } @Override public void testProcess(final BPMNProcess process) { for (TestCase testCase : process.getTestCases()) { BPMNTester bpmnTester = new BPMNTester(); int testCaseNumber = testCase.getNumber(); bpmnTester.setSource(process.getTargetTestSrcPathWithCase(testCaseNumber)); bpmnTester.setTarget(process.getTargetTestBinPathWithCase(testCaseNumber)); bpmnTester.setReportPath(process.getTargetReportsPathWithCase(testCaseNumber)); BPMNProcessInstanceOutcomeChecker checker = createProcessOutcomeChecker(process.getName()); new GenericBPMNTester(process, testCase, getInstanceLogFile(process.getName(), testCaseNumber), bpmnTester, checker, checker, new JbpmProcessStarter(getServerLog()) ).runTest(); } new BPMNTestcaseMerger(process.getTargetReportsPath()).mergeTestCases(); } private Path getInstanceLogFile(String processName, int testCaseNumber) { return getJbpmInstallerPath().resolve("log-" + processName + "-" + testCaseNumber + ".txt"); } @Override public BPMNProcessStarter getProcessStarter() { return new JbpmProcessStarter(getServerLog()); } @Override public Path getLogForInstance(String processName, String instanceId) { return getInstanceLogFile(processName, Integer.parseInt(instanceId)); } protected static String getDeploymentId(String name) { return "de.uniba.dsg" + ":" + name + ":" + "1.0"; } @Override public boolean isDeployed(QName process) { try { JbpmApiBasedProcessInstanceOutcomeChecker checker = createProcessOutcomeChecker(process.getLocalPart()); return checker.isProcessDeployed(); } catch (Exception e) { return false; } } @Override public void undeploy(QName process) { String deploymentId = getDeploymentId(process.getLocalPart()); JbpmDeployer deployer = new JbpmDeployer(getJbpmnUrl(), deploymentId); deployer.undeploy(); TimeoutRepository.getTimeout("Jbpm.undeploy").waitFor(() -> !isDeployed(process)); } @Override public void buildTest(final BPMNProcess process) { BPMNTestBuilder builder = new BPMNTestBuilder(); builder.setPackageString(process.getPackageID()); builder.setLogDir(getJbpmInstallerPath()); builder.setProcess(process); builder.buildTests(); } protected JbpmApiBasedProcessInstanceOutcomeChecker createProcessOutcomeChecker(String name) { String url = getJbpmnUrl() + "/rest/runtime/" + getDeploymentId(name) + "/history/instance/1"; String deployCheckUrl = getJbpmnUrl() + "/rest/deployment/" + getDeploymentId(name); return new JbpmApiBasedProcessInstanceOutcomeChecker(url, deployCheckUrl); } }