package betsy.bpmn.engines.camunda; 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 java.util.Optional; import javax.xml.namespace.QName; import betsy.bpmn.engines.AbstractBPMNEngine; 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.timeouts.timeout.TimeoutRepository; import betsy.common.util.ClasspathHelper; import betsy.common.util.FileTypes; import org.apache.log4j.Logger; import pebl.ProcessLanguage; import pebl.benchmark.test.TestCase; import static betsy.bpmn.engines.BPMNProcessInstanceOutcomeChecker.ProcessInstanceOutcome.UNDEPLOYED_PROCESS; public class CamundaEngine extends AbstractBPMNEngine { private static final Logger LOGGER = Logger.getLogger(CamundaEngine.class); @Override public EngineExtended getEngineObject() { return new EngineExtended(ProcessLanguage.BPMN, "camunda", "7.0.0", LocalDate.of(2013, 8, 31), "Apache-2.0"); } public String getCamundaUrl() { return "http://localhost:8080"; } public String getTomcatName() { return "apache-tomcat-7.0.33"; } public Path getTomcatDir() { return getServerPath().resolve("server").resolve(getTomcatName()); } @Override public Path getXsltPath() { return ClasspathHelper.getFilesystemPathFromClasspathPath("/bpmn/camunda"); } @Override public void deploy(String name, Path path) { FileTasks.copyFileIntoFolder(path, getTomcatDir().resolve("webapps")); //wait until it is deployed final Path logFile = FileTasks.findFirstMatchInFolder(getTomcatLogsDir(), "catalina*"); if (logFile == null) { throw new IllegalStateException("Could not find catalina log file in " + getTomcatLogsDir()); } TimeoutRepository.getTimeout("Camunda.deploy").waitFor(() -> FileTasks.hasFileSpecificSubstring(logFile, "Process Application " + name + " Application successfully deployed.") || FileTasks.hasFileSpecificSubstring(logFile, "Process application " + name + " Application successfully deployed") || FileTasks.hasFileSpecificSubstring(logFile, "Context [/" + name + "] startup failed due to previous errors")); } @Override public boolean isDeployed(QName process) { try { return !UNDEPLOYED_PROCESS.equals(new CamundaApiBasedProcessInstanceOutcomeChecker().checkProcessOutcome(process.getLocalPart())); } catch (Exception e) { return false; } } @Override public void undeploy(QName process) { LOGGER.info("Undeploying process " + process); FileTasks.deleteFile(getTomcatDir().resolve("webapps").resolve(process.getLocalPart() + ".war")); WaitTasks.sleep(5000); } @Override public Path buildArchives(final BPMNProcess process) { Path targetProcessPath = process.getTargetProcessPath(); FileTasks.mkdirs(targetProcessPath); FileTasks.copyFileIntoFolder(process.getProcess(), targetProcessPath); Path targetProcessFilePath = targetProcessPath.resolve(process.getProcessFileName()); XSLTTasks.transform(getXsltPath().resolve("../scriptTask.xsl"), targetProcessFilePath, targetProcessPath.resolve(process.getName() + ".bpmn-temp"), "processName", process.getName()); XSLTTasks.transform(getXsltPath().resolve("camunda.xsl"), targetProcessPath.resolve(process.getName() + ".bpmn-temp"), targetProcessPath.resolve(process.getName() + FileTypes.BPMN)); FileTasks.deleteFile(targetProcessPath.resolve(process.getName() + ".bpmn-temp")); Path targetWarWebinfClassesPath = process.getTargetPath().resolve("war/WEB-INF/classes"); FileTasks.mkdirs(targetWarWebinfClassesPath); FileTasks.copyFileIntoFolder(targetProcessFilePath, targetWarWebinfClassesPath); CamundaResourcesGenerator generator = new CamundaResourcesGenerator(); generator.setGroupId("de.uniba.dsg"); generator.setProcessName(process.getName()); Path warFile = process.getTargetPath().resolve("war"); generator.setDestDir(warFile); generator.setVersion("1.0"); return generator.generateWar(); } @Override public void buildTest(final BPMNProcess process) { BPMNTestBuilder builder = new BPMNTestBuilder(); builder.setPackageString(process.getPackageID()); builder.setLogDir(getTomcatDir().resolve("bin")); builder.setProcess(process); builder.buildTests(); } @Override public String getEndpointUrl(String name) { return "http://localhost:8080/engine-rest/engine/default"; } @Override public List<Path> getLogs() { List<Path> result = new LinkedList<>(); result.addAll(FileTasks.findAllInFolder(getTomcatLogsDir())); result.addAll(FileTasks.findAllInFolder(getTomcatDir().resolve("bin"), "log*.txt")); return result; } private Path getTomcatLogsDir() { return getTomcatDir().resolve("logs"); } @Override public void install() { CamundaInstaller installer = new CamundaInstaller(); installer.setDestinationDir(getServerPath()); installer.setTomcatName(getTomcatName()); installer.setGroovyFile(Optional.of("groovy-all-2.2.0.jar")); installer.install(); } @Override public void startup() { Path pathToJava7 = Configuration.getJava7Home(); Map<String, String> map = new LinkedHashMap<>(2); map.put("JAVA_HOME", pathToJava7.toString()); map.put("JRE_HOME", pathToJava7.toString()); ConsoleTasks.executeOnWindowsAndIgnoreError(ConsoleTasks.CliCommand.build(getServerPath(), "camunda_startup.bat"), map); ConsoleTasks.executeOnUnixAndIgnoreError(ConsoleTasks.CliCommand.build(getServerPath().resolve("camunda_startup.sh")), map); TimeoutRepository.getTimeout("Camunda.startup").waitForAvailabilityOfUrl(getCamundaUrl()); } @Override public void shutdown() { if (!Files.exists(getServerPath())) { LOGGER.info("Shutdown of " + getName() + " not possible as " + getServerPath() + " does not exist."); return; } Path shutdownShellScript = getServerPath().resolve("camunda_shutdown.sh"); if (!Files.exists(shutdownShellScript)) { LOGGER.info("Shutdown shell script " + shutdownShellScript + " does not exist"); } Path pathToJava7 = Configuration.getJava7Home(); Map<String, String> map = new LinkedHashMap<>(2); map.put("JAVA_HOME", pathToJava7.toString()); map.put("JRE_HOME", pathToJava7.toString()); ConsoleTasks.executeOnWindowsAndIgnoreError(ConsoleTasks.CliCommand.build(getServerPath().resolve("camunda_shutdown.bat")), map); ConsoleTasks.executeOnWindowsAndIgnoreError(ConsoleTasks.CliCommand.build("taskkill").values("/FI", "WINDOWTITLE eq Tomcat")); ConsoleTasks.executeOnUnixAndIgnoreError(ConsoleTasks.CliCommand.build(shutdownShellScript), map); } @Override public boolean isRunning() { return URLTasks.isUrlAvailable(getCamundaUrl()); } @Override public void testProcess(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)); new GenericBPMNTester(process, testCase, getInstanceLogFile(process.getName(), testCaseNumber), bpmnTester, new CamundaApiBasedProcessInstanceOutcomeChecker(), new CamundaLogBasedProcessInstanceOutcomeChecker(FileTasks.findFirstMatchInFolder(getTomcatLogsDir(), "catalina*")), new CamundaProcessStarter() ).runTest(); } new BPMNTestcaseMerger(process.getTargetReportsPath()).mergeTestCases(); } private Path getInstanceLogFile(String processName, int testCaseNumber) { return getTomcatDir().resolve("bin").resolve("log-" + processName + "-" + testCaseNumber + ".txt"); } @Override public BPMNProcessStarter getProcessStarter() { return new CamundaProcessStarter(); } @Override public Path getLogForInstance(String processName, String instanceId) { return getInstanceLogFile(processName, Integer.parseInt(instanceId)); } }