Commit f66210e57dcdaaf22085c92614c07c93ffa2f511

Authored by YunaiV
1 parent a970ea93

fix(bpm): 按 Flowable 版本重整 DM8 适配补丁

支持 Flowable 6.8.0 和 8.0.0,移除原类覆盖,统一各 Spring 引擎的达梦方言与插入配置。
修复 Liquibase SPI 注册冲突及事件、DMN 子引擎批量插入失败,补充独立回归工程。
Showing 21 changed files with 811 additions and 2853 deletions
sql/dm/flowable-patch-6.8.0/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/DmFlowableConfiguration.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.config;
  2 +
  3 +import org.flowable.common.engine.impl.AbstractEngineConfiguration;
  4 +import org.springframework.beans.factory.config.BeanPostProcessor;
  5 +import org.springframework.context.annotation.Bean;
  6 +import org.springframework.context.annotation.Configuration;
  7 +
  8 +import java.sql.Connection;
  9 +import java.sql.SQLException;
  10 +
  11 +/**
  12 + * 达梦数据库的 Flowable 配置
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +@Configuration(proxyBeanMethods = false)
  17 +public class DmFlowableConfiguration {
  18 +
  19 + /**
  20 + * 在 Spring 管理的各个 Flowable 引擎初始化前设置达梦方言与插入策略
  21 + */
  22 + @Bean
  23 + public static BeanPostProcessor dmEngineConfigurationBeanPostProcessor() {
  24 + return new BeanPostProcessor() {
  25 +
  26 + @Override
  27 + public Object postProcessBeforeInitialization(Object bean, String beanName) {
  28 + if (!(bean instanceof AbstractEngineConfiguration)) {
  29 + return bean;
  30 + }
  31 + AbstractEngineConfiguration configuration = (AbstractEngineConfiguration) bean;
  32 + if (configuration.getDataSource() == null) {
  33 + return bean;
  34 + }
  35 + // 在各个 Spring 引擎初始化前处理,避免子引擎重新开启批量插入;使用实际数据源识别达梦
  36 + try (Connection connection = configuration.getDataSource().getConnection()) {
  37 + if ("DM DBMS".equalsIgnoreCase(connection.getMetaData().getDatabaseProductName())) {
  38 + configuration.setDatabaseType("oracle");
  39 + // 特殊:达梦普通用户执行 Oracle INSERT ALL 时可能访问 SYS.SYSDUAL2,改为普通插入,避免扩大数据库权限
  40 + configuration.setBulkInsertEnabled(false);
  41 + }
  42 + } catch (SQLException e) {
  43 + throw new IllegalStateException("读取 Flowable 数据库类型失败", e);
  44 + }
  45 + return bean;
  46 + }
  47 + };
  48 + }
  49 +
  50 +}
sql/dm/flowable-patch-6.8.0/src/main/java/liquibase/database/core/DmDatabase.java 0 → 100644
  1 +package liquibase.database.core;
  2 +
  3 +import liquibase.database.DatabaseConnection;
  4 +import liquibase.exception.DatabaseException;
  5 +
  6 +/**
  7 + * 达梦数据库的 Liquibase 适配,复用 Oracle 的字段类型与建表语法
  8 + *
  9 + * @author 芋道源码
  10 + */
  11 +public class DmDatabase extends OracleDatabase {
  12 +
  13 + @Override
  14 + public String getShortName() {
  15 + // 独立注册达梦,避免与 Oracle 的 SPI 注册键及优先级冲突
  16 + return "dm";
  17 + }
  18 +
  19 + @Override
  20 + protected String getDefaultDatabaseProductName() {
  21 + return "DM DBMS";
  22 + }
  23 +
  24 + @Override
  25 + public boolean isCorrectDatabaseImplementation(DatabaseConnection connection) throws DatabaseException {
  26 + return "DM DBMS".equalsIgnoreCase(connection.getDatabaseProductName());
  27 + }
  28 +
  29 + @Override
  30 + public String getDefaultDriver(String url) {
  31 + return url != null && url.startsWith("jdbc:dm:") ? "dm.jdbc.driver.DmDriver" : null;
  32 + }
  33 +
  34 + @Override
  35 + public Integer getDefaultPort() {
  36 + return 5236;
  37 + }
  38 +
  39 + @Override
  40 + public int getDatabaseMinorVersion() throws DatabaseException {
  41 + // 特殊:部分达梦驱动返回非数字次版本号,避免 Oracle 版本判断时解析失败
  42 + try {
  43 + return super.getDatabaseMinorVersion();
  44 + } catch (DatabaseException e) {
  45 + return 0;
  46 + }
  47 + }
  48 +
  49 +}
sql/dm/flowable-patch-6.8.0/src/main/resources/META-INF/services/liquibase.database.Database 0 → 100644
  1 +liquibase.database.core.DmDatabase
sql/dm/flowable-patch-8.0.0/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/DmFlowableConfiguration.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.config;
  2 +
  3 +import org.flowable.common.engine.impl.AbstractEngineConfiguration;
  4 +import org.springframework.beans.factory.config.BeanPostProcessor;
  5 +import org.springframework.context.annotation.Bean;
  6 +import org.springframework.context.annotation.Configuration;
  7 +
  8 +import java.sql.Connection;
  9 +import java.sql.SQLException;
  10 +
  11 +/**
  12 + * 达梦数据库的 Flowable 配置
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +@Configuration(proxyBeanMethods = false)
  17 +public class DmFlowableConfiguration {
  18 +
  19 + /**
  20 + * 在 Spring 管理的各个 Flowable 引擎初始化前设置达梦方言与插入策略
  21 + */
  22 + @Bean
  23 + public static BeanPostProcessor dmEngineConfigurationBeanPostProcessor() {
  24 + return new BeanPostProcessor() {
  25 +
  26 + @Override
  27 + public Object postProcessBeforeInitialization(Object bean, String beanName) {
  28 + if (!(bean instanceof AbstractEngineConfiguration)) {
  29 + return bean;
  30 + }
  31 + AbstractEngineConfiguration configuration = (AbstractEngineConfiguration) bean;
  32 + if (configuration.getDataSource() == null) {
  33 + return bean;
  34 + }
  35 + // 在各个 Spring 引擎初始化前处理,避免子引擎重新开启批量插入;使用实际数据源识别达梦
  36 + try (Connection connection = configuration.getDataSource().getConnection()) {
  37 + if ("DM DBMS".equalsIgnoreCase(connection.getMetaData().getDatabaseProductName())) {
  38 + configuration.setDatabaseType("oracle");
  39 + // 特殊:达梦普通用户执行 Oracle INSERT ALL 时可能访问 SYS.SYSDUAL2,改为普通插入,避免扩大数据库权限
  40 + configuration.setBulkInsertEnabled(false);
  41 + }
  42 + } catch (SQLException e) {
  43 + throw new IllegalStateException("读取 Flowable 数据库类型失败", e);
  44 + }
  45 + return bean;
  46 + }
  47 + };
  48 + }
  49 +
  50 +}
sql/dm/flowable-patch-tests/README.md 0 → 100644
  1 +# Flowable 达梦补丁回归测试
  2 +
  3 +本目录是独立的 Maven 测试工程,直接编译同级 `flowable-patch-${flowable.version}` 补丁目录的源码,验证补丁本身。它不加入主工程模块,不参与业务默认构建,也不要复制到业务模块。
  4 +
  5 +补丁安装请阅读项目文档《工作流(达梦适配)》,本文只说明如何测试。
  6 +
  7 +## 1. 版本矩阵
  8 +
  9 +| Profile | JDK | Spring Boot | Flowable | 被测补丁 |
  10 +| --- | --- | --- | --- | --- |
  11 +| `jdk8` | JDK8 | 2.7.18 | 6.8.0 | `flowable-patch-6.8.0` |
  12 +| 默认 | JDK17 或 JDK25 | 3.5.15 | 8.0.0 | `flowable-patch-8.0.0` |
  13 +| `sb4` | JDK25 | 4.1.1 | 8.0.0 | `flowable-patch-8.0.0` |
  14 +
  15 +各组合的编译输出位于 `target/<Spring Boot 版本>-<Flowable 版本>`,互不覆盖。
  16 +
  17 +## 2. 准备数据库
  18 +
  19 +先创建独立的非生产测试账号,只授予该测试 schema 的建表权限,**不要使用生产库**。6.8.0 与 8.0.0 请使用不同账号/schema 分别测试,不能在同一工作流 schema 混跑两个 Flowable 版本。
  20 +
  21 +通过环境变量指定数据库,密码由本地环境提供,不写入 Git:
  22 +
  23 +```bash
  24 +export DM_JDBC_URL='jdbc:dm://127.0.0.1:15236'
  25 +export DM_JDBC_USER='FLOWABLE_TEST'
  26 +export DM_JDBC_PASSWORD='本地测试密码'
  27 +```
  28 +
  29 +## 3. 执行测试
  30 +
  31 +在 `ruoyi-vue-pro` 仓库根目录(包含 `sql/` 目录的一级)执行:
  32 +
  33 +```bash
  34 +# 使用 JDK8:Spring Boot 2.7.18 + Flowable 6.8.0
  35 +mvn -f sql/dm/flowable-patch-tests/pom.xml -Pjdk8 test
  36 +
  37 +# 使用 JDK17 或 JDK25:Spring Boot 3.5.15 + Flowable 8.0.0
  38 +mvn -f sql/dm/flowable-patch-tests/pom.xml test
  39 +
  40 +# 使用 JDK25:Spring Boot 4.1.1 + Flowable 8.0.0
  41 +mvn -f sql/dm/flowable-patch-tests/pom.xml -Psb4 test
  42 +```
  43 +
  44 +未配置 `DM_JDBC_URL` 时,只运行基于 H2 的非达梦检查(其它数据库不受补丁影响;6.8.0 另检查 SPI 注册顺序),真实达梦用例会在 Maven 输出中显示为 `Skipped`。此时**不能据此认定达梦适配通过**;验收时应确认真实达梦用例没有被跳过。
  45 +
  46 +## 4. 测试覆盖与边界
  47 +
  48 +覆盖 Spring Boot 自动装配(不手工关闭应用级 Liquibase)、首次建表与保持 `flowable.database-schema-update: true` 的重复启动、流程部署/发起/两级审批、退回与拒绝、取消、长文本和布尔变量、历史与分页、事务回滚、并行网关、定时 Job 执行、DMN 建表与决策,以及自动装配后一次部署多个 DMN/事件定义。6.8.0 另覆盖 Oracle/DM 两种 SPI 注册顺序,以及 DM 元数据与布尔类型识别。
  49 +
  50 +不包含完整芋道 Web 服务(微服务的网关、注册中心等)及前端浏览器验收,也不代表已验证所有流程模型、并发性能、跨版本历史库升级,或所有第三方 Flowable 用法。补丁合并到业务模块后,仍需在实际项目中验证启动及流程功能。
  51 +
  52 +## 5. 实现说明
  53 +
  54 +- 两个版本的 `DmFlowableConfiguration` 保持一致。通过 Spring `BeanPostProcessor`,在各个 Flowable 引擎配置 Bean 初始化前,按引擎实际连接的 JDBC 元数据识别达梦,设置工作流 Oracle 方言及普通插入,覆盖主引擎和 Spring 事件/DMN 子引擎。不修改 Flowable 原类,不替换全局 MyBatis `DatabaseIdProvider`,不依赖数据源名称或 `yudao.dameng.enabled` 开关。
  55 +- 对达梦关闭 `INSERT ALL` 批量插入,避免部分 DM8 环境下普通用户访问 `SYS.SYSDUAL2` 失败,无需给业务账号授予 DBA。仅关闭主引擎不够,子引擎会将自己的批量实体重新注册到共享 SQL 工厂。代价是批量写入吞吐可能降低,需按实际负载压测。
  56 +- 补丁只处理 Spring 管理的 Flowable 配置 Bean。手动 `new` 的非 Bean 配置、独立接入的其它引擎不会被自动覆盖,需要自行设置方言及插入策略。
  57 +- 仅 6.8.0 使用 Liquibase SPI 注册 `DmDatabase extends OracleDatabase`,复用 Oracle 的字段、布尔值及 schema 识别逻辑,不覆盖 `BooleanType`。注册短名为独立的 `dm`,避免与原生 Oracle 实现竞争同一个注册键;Flowable 方言仍为 `oracle`,两者是不同机制。Flowable 6.8.0 自带的环境后处理器默认关闭 Spring Boot 应用级 Liquibase,内部事件/DMN 的 Liquibase 建表仍正常执行。
  58 +- 8.0.0 的事件/DMN 已改用 SQL 脚本,补丁仅包含 Spring 配置,不引入 Liquibase。若额外加入 Liquibase 依赖,Boot 3 会默认查找应用级 changelog 导致启动失败;不要用 `spring.liquibase.enabled=false` 掩盖该问题。
  59 +- DM 的 `COMPATIBLE_MODE` 是数据库配置,`oracle` 是 Flowable 方言,两者不是同一设置。不要在已有库上直接更换方言、重建表或混用两个 Flowable 版本;升级现有工作流数据库须另行备份、验证官方升级脚本,补丁不是升级脚本。
sql/dm/flowable-patch-tests/pom.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <modelVersion>4.0.0</modelVersion>
  6 + <groupId>cn.iocoder.boot</groupId>
  7 + <artifactId>dm-flowable-patch-tests</artifactId>
  8 + <version>1.0-SNAPSHOT</version>
  9 + <properties>
  10 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  11 + <flowable.version>8.0.0</flowable.version>
  12 + <spring.boot.version>3.5.15</spring.boot.version>
  13 + <maven.compiler.release>17</maven.compiler.release>
  14 + </properties>
  15 + <dependencyManagement>
  16 + <dependencies>
  17 + <dependency>
  18 + <groupId>org.springframework.boot</groupId>
  19 + <artifactId>spring-boot-dependencies</artifactId>
  20 + <version>${spring.boot.version}</version>
  21 + <type>pom</type>
  22 + <scope>import</scope>
  23 + </dependency>
  24 + </dependencies>
  25 + </dependencyManagement>
  26 + <dependencies>
  27 + <dependency>
  28 + <groupId>org.flowable</groupId>
  29 + <artifactId>flowable-spring-boot-starter-process</artifactId>
  30 + <version>${flowable.version}</version>
  31 + </dependency>
  32 + <dependency>
  33 + <groupId>org.flowable</groupId>
  34 + <artifactId>flowable-dmn-spring-configurator</artifactId>
  35 + <version>${flowable.version}</version>
  36 + </dependency>
  37 + <dependency>
  38 + <groupId>com.dameng</groupId>
  39 + <artifactId>DmJdbcDriver18</artifactId>
  40 + <version>8.1.3.140</version>
  41 + <scope>test</scope>
  42 + </dependency>
  43 + <dependency>
  44 + <groupId>com.h2database</groupId>
  45 + <artifactId>h2</artifactId>
  46 + <scope>test</scope>
  47 + </dependency>
  48 + <dependency>
  49 + <groupId>org.junit.jupiter</groupId>
  50 + <artifactId>junit-jupiter</artifactId>
  51 + <scope>test</scope>
  52 + </dependency>
  53 + </dependencies>
  54 + <build>
  55 + <directory>${project.basedir}/target/${spring.boot.version}-${flowable.version}</directory>
  56 + <sourceDirectory>../flowable-patch-${flowable.version}/src/main/java</sourceDirectory>
  57 + <resources>
  58 + <resource>
  59 + <directory>../flowable-patch-${flowable.version}/src/main/resources</directory>
  60 + </resource>
  61 + </resources>
  62 + <plugins>
  63 + <plugin>
  64 + <groupId>org.apache.maven.plugins</groupId>
  65 + <artifactId>maven-compiler-plugin</artifactId>
  66 + <version>3.13.0</version>
  67 + </plugin>
  68 + <plugin>
  69 + <groupId>org.apache.maven.plugins</groupId>
  70 + <artifactId>maven-surefire-plugin</artifactId>
  71 + <version>3.5.3</version>
  72 + </plugin>
  73 + </plugins>
  74 + </build>
  75 + <profiles>
  76 + <profile>
  77 + <id>jdk8</id>
  78 + <properties>
  79 + <flowable.version>6.8.0</flowable.version>
  80 + <spring.boot.version>2.7.18</spring.boot.version>
  81 + <maven.compiler.release>8</maven.compiler.release>
  82 + </properties>
  83 + <dependencies>
  84 + <dependency>
  85 + <groupId>org.liquibase</groupId>
  86 + <artifactId>liquibase-core</artifactId>
  87 + </dependency>
  88 + </dependencies>
  89 + <build>
  90 + <plugins>
  91 + <plugin>
  92 + <groupId>org.codehaus.mojo</groupId>
  93 + <artifactId>build-helper-maven-plugin</artifactId>
  94 + <version>3.6.1</version>
  95 + <executions>
  96 + <execution>
  97 + <id>liquibase-patch-tests</id>
  98 + <phase>generate-test-sources</phase>
  99 + <goals><goal>add-test-source</goal></goals>
  100 + <configuration>
  101 + <sources><source>src/test/liquibase</source></sources>
  102 + </configuration>
  103 + </execution>
  104 + </executions>
  105 + </plugin>
  106 + </plugins>
  107 + </build>
  108 + </profile>
  109 + <profile>
  110 + <id>sb4</id>
  111 + <properties>
  112 + <spring.boot.version>4.1.1</spring.boot.version>
  113 + <maven.compiler.release>25</maven.compiler.release>
  114 + </properties>
  115 + </profile>
  116 + </profiles>
  117 +</project>
sql/dm/flowable-patch-tests/src/test/java/cn/iocoder/yudao/module/bpm/DmFlowablePatchTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.framework.flowable.config.DmFlowableConfiguration;
  4 +import org.flowable.engine.ProcessEngine;
  5 +import org.flowable.engine.history.HistoricProcessInstance;
  6 +import org.flowable.engine.runtime.ProcessInstance;
  7 +import org.flowable.dmn.engine.DmnEngine;
  8 +import org.flowable.dmn.spring.SpringDmnEngineConfiguration;
  9 +import org.flowable.eventregistry.impl.EventRegistryEngine;
  10 +import org.flowable.eventregistry.api.EventDeployment;
  11 +import org.flowable.spring.SpringProcessEngineConfiguration;
  12 +import org.flowable.task.api.Task;
  13 +import org.junit.jupiter.api.Test;
  14 +import org.springframework.boot.WebApplicationType;
  15 +import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
  16 +import org.springframework.boot.builder.SpringApplicationBuilder;
  17 +import org.springframework.context.ConfigurableApplicationContext;
  18 +import org.springframework.context.annotation.Bean;
  19 +import org.springframework.context.annotation.Configuration;
  20 +import org.springframework.context.annotation.Import;
  21 +import org.springframework.jdbc.datasource.DataSourceTransactionManager;
  22 +import org.springframework.jdbc.datasource.DriverManagerDataSource;
  23 +import org.springframework.transaction.support.TransactionTemplate;
  24 +
  25 +import javax.sql.DataSource;
  26 +import java.sql.Connection;
  27 +import java.util.Collections;
  28 +import java.util.List;
  29 +import java.util.Map;
  30 +import java.util.UUID;
  31 +import java.nio.charset.StandardCharsets;
  32 +import java.io.ByteArrayOutputStream;
  33 +import java.io.InputStream;
  34 +
  35 +import static org.junit.jupiter.api.Assertions.*;
  36 +import static org.junit.jupiter.api.Assumptions.assumeTrue;
  37 +
  38 +/**
  39 + * 达梦补丁的版本兼容与真实数据库回归测试
  40 + *
  41 + * @author 芋道源码
  42 + */
  43 +class DmFlowablePatchTest {
  44 +
  45 + @Test
  46 + void testOtherDatabaseUnchanged() throws Exception {
  47 + DriverManagerDataSource dataSource = new DriverManagerDataSource("jdbc:h2:mem:dm_patch_regression", "sa", "");
  48 + SpringProcessEngineConfiguration configuration = configuration(dataSource);
  49 + configureDm(configuration);
  50 + assertNull(configuration.getDatabaseType());
  51 + assertTrue(configuration.isBulkInsertEnabled());
  52 + }
  53 +
  54 + @Test
  55 + void testDmSchemaAndProcess() throws Exception {
  56 + DataSource dataSource = dmDataSource();
  57 + try (Connection connection = dataSource.getConnection()) {
  58 + assertEquals("DM DBMS", connection.getMetaData().getDatabaseProductName());
  59 + }
  60 + String instanceId;
  61 + SpringProcessEngineConfiguration first = configuration(dataSource);
  62 + first.setDatabaseSchemaUpdate("true");
  63 + configureDm(first);
  64 + assertEquals("oracle", first.getDatabaseType());
  65 + ProcessEngine engine = first.buildProcessEngine();
  66 + try {
  67 + engine.getRepositoryService().createDeployment().addClasspathResource("approval.bpmn20.xml").deploy();
  68 + ProcessInstance instance = engine.getRuntimeService().startProcessInstanceByKey("dmApproval", "dm-test",
  69 + Collections.<String, Object>singletonMap("amount", 100));
  70 + instanceId = instance.getId();
  71 + Task task = engine.getTaskService().createTaskQuery().processInstanceId(instanceId).singleResult();
  72 + assertEquals("审批一", task.getName());
  73 + engine.getTaskService().setAssignee(task.getId(), "1");
  74 + engine.getTaskService().complete(task.getId());
  75 + assertEquals("审批二", engine.getTaskService().createTaskQuery().processInstanceId(instanceId).singleResult().getName());
  76 + } finally {
  77 + engine.close();
  78 + }
  79 + // 再次开启 schema-update,验证已存在的工作流表不会重复创建
  80 + SpringProcessEngineConfiguration second = configuration(dataSource);
  81 + second.setDatabaseSchemaUpdate("true");
  82 + configureDm(second);
  83 + engine = second.buildProcessEngine();
  84 + try {
  85 + Task task = engine.getTaskService().createTaskQuery().processInstanceId(instanceId).singleResult();
  86 + engine.getTaskService().complete(task.getId());
  87 + assertNull(engine.getRuntimeService().createProcessInstanceQuery().processInstanceId(instanceId).singleResult());
  88 + HistoricProcessInstance history = engine.getHistoryService().createHistoricProcessInstanceQuery()
  89 + .processInstanceId(instanceId).singleResult();
  90 + assertNotNull(history.getEndTime());
  91 + assertEquals(2, engine.getHistoryService().createHistoricTaskInstanceQuery().processInstanceId(instanceId).finished().count());
  92 + assertEquals(1, engine.getRepositoryService().createProcessDefinitionQuery().processDefinitionKey("dmApproval").listPage(0, 1).size());
  93 + } finally {
  94 + engine.close();
  95 + }
  96 + }
  97 +
  98 + @Test
  99 + void testDmReturnAndReject() {
  100 + ProcessEngine engine = dmEngine();
  101 + try {
  102 + engine.getRepositoryService().createDeployment().addClasspathResource("approval.bpmn20.xml").deploy();
  103 + ProcessInstance instance = engine.getRuntimeService().startProcessInstanceByKey("dmApproval");
  104 + Task task = engine.getTaskService().createTaskQuery().processInstanceId(instance.getId()).singleResult();
  105 + engine.getTaskService().complete(task.getId());
  106 + engine.getRuntimeService().createChangeActivityStateBuilder().processInstanceId(instance.getId())
  107 + .moveActivityIdTo("second", "first").changeState();
  108 + assertEquals("审批一", engine.getTaskService().createTaskQuery().processInstanceId(instance.getId()).singleResult().getName());
  109 + engine.getRuntimeService().deleteProcessInstance(instance.getId(), "审批拒绝");
  110 + assertEquals("审批拒绝", engine.getHistoryService().createHistoricProcessInstanceQuery()
  111 + .processInstanceId(instance.getId()).singleResult().getDeleteReason());
  112 + } finally {
  113 + engine.close();
  114 + }
  115 + }
  116 +
  117 + @Test
  118 + void testDmCancelAndVariables() {
  119 + ProcessEngine engine = dmEngine();
  120 + try {
  121 + engine.getRepositoryService().createDeployment().addClasspathResource("approval.bpmn20.xml").deploy();
  122 + String longText = String.join("", Collections.nCopies(3000, "达梦🙂"));
  123 + ProcessInstance instance = engine.getRuntimeService().startProcessInstanceByKey("dmApproval", "cancel-test",
  124 + Collections.<String, Object>singletonMap("longText", longText));
  125 + engine.getRuntimeService().setVariable(instance.getId(), "approved", true);
  126 + assertEquals(longText, engine.getRuntimeService().getVariable(instance.getId(), "longText"));
  127 + assertEquals(true, engine.getRuntimeService().getVariable(instance.getId(), "approved"));
  128 + engine.getRuntimeService().deleteProcessInstance(instance.getId(), "发起人取消");
  129 + assertEquals("发起人取消", engine.getHistoryService().createHistoricProcessInstanceQuery()
  130 + .processInstanceBusinessKey("cancel-test").orderByProcessInstanceStartTime().desc().listPage(0, 1).get(0).getDeleteReason());
  131 + assertEquals(longText, engine.getHistoryService().createHistoricVariableInstanceQuery()
  132 + .processInstanceId(instance.getId()).variableName("longText").singleResult().getValue());
  133 + } finally {
  134 + engine.close();
  135 + }
  136 + }
  137 +
  138 + @Test
  139 + void testDmParallelGateway() {
  140 + ProcessEngine engine = dmEngine();
  141 + try {
  142 + engine.getRepositoryService().createDeployment().addClasspathResource("parallel.bpmn20.xml").deploy();
  143 + ProcessInstance instance = engine.getRuntimeService().startProcessInstanceByKey("dmParallel");
  144 + List<Task> tasks = engine.getTaskService().createTaskQuery().processInstanceId(instance.getId()).list();
  145 + assertEquals(2, tasks.size());
  146 + engine.getTaskService().complete(tasks.get(0).getId());
  147 + assertEquals(1, engine.getRuntimeService().createProcessInstanceQuery().processInstanceId(instance.getId()).count());
  148 + engine.getTaskService().complete(tasks.get(1).getId());
  149 + assertEquals(0, engine.getRuntimeService().createProcessInstanceQuery().processInstanceId(instance.getId()).count());
  150 + } finally {
  151 + engine.close();
  152 + }
  153 + }
  154 +
  155 + @Test
  156 + void testDmTimer() {
  157 + ProcessEngine engine = dmEngine();
  158 + try {
  159 + engine.getRepositoryService().createDeployment().addClasspathResource("timer.bpmn20.xml").deploy();
  160 + ProcessInstance instance = engine.getRuntimeService().startProcessInstanceByKey("dmTimer");
  161 + String timerId = engine.getManagementService().createTimerJobQuery().processInstanceId(instance.getId()).singleResult().getId();
  162 + String jobId = engine.getManagementService().moveTimerToExecutableJob(timerId).getId();
  163 + engine.getManagementService().executeJob(jobId);
  164 + assertEquals(0, engine.getManagementService().createTimerJobQuery().processInstanceId(instance.getId()).count());
  165 + assertEquals("定时后审批", engine.getTaskService().createTaskQuery().processInstanceId(instance.getId()).singleResult().getName());
  166 + engine.getRuntimeService().deleteProcessInstance(instance.getId(), "测试结束");
  167 + } finally {
  168 + engine.close();
  169 + }
  170 + }
  171 +
  172 + @Test
  173 + void testDmDmnSchemaAndDecision() {
  174 + DataSource dataSource = dmDataSource();
  175 + SpringDmnEngineConfiguration configuration = new SpringDmnEngineConfiguration();
  176 + configuration.setDataSource(dataSource);
  177 + configuration.setTransactionManager(new DataSourceTransactionManager(dataSource));
  178 + configureDm(configuration);
  179 + configuration.setDatabaseSchemaUpdate("true");
  180 + DmnEngine engine = configuration.buildDmnEngine();
  181 + try {
  182 + engine.getDmnRepositoryService().createDeployment().addClasspathResource("amount.dmn").deploy();
  183 + Map<String, Object> result = engine.getDmnDecisionService().createExecuteDecisionBuilder()
  184 + .decisionKey("dmAmount").variable("amount", 100).executeWithSingleResult();
  185 + assertEquals("通过", result.get("result"));
  186 + } finally {
  187 + engine.close();
  188 + }
  189 + // DMN 在 6.8.0 使用 Liquibase,重复启动必须能识别已存在的 changelog 表
  190 + configuration = new SpringDmnEngineConfiguration();
  191 + configuration.setDataSource(dataSource);
  192 + configuration.setTransactionManager(new DataSourceTransactionManager(dataSource));
  193 + configureDm(configuration);
  194 + configuration.setDatabaseSchemaUpdate("true");
  195 + engine = configuration.buildDmnEngine();
  196 + engine.close();
  197 + }
  198 +
  199 + @Test
  200 + void testBootAutoConfiguration() {
  201 + dmDataSource();
  202 + try (ConfigurableApplicationContext context = new SpringApplicationBuilder(TestApplication.class)
  203 + .web(WebApplicationType.NONE)
  204 + .properties("flowable.database-schema-update=true", "flowable.async-executor-activate=false",
  205 + "logging.level.root=WARN", "spring.main.banner-mode=off")
  206 + .run()) {
  207 + ProcessEngine engine = context.getBean(ProcessEngine.class);
  208 + assertEquals("oracle", engine.getProcessEngineConfiguration().getDatabaseType());
  209 + assertFalse(((SpringProcessEngineConfiguration) engine.getProcessEngineConfiguration()).isBulkInsertEnabled());
  210 + assertNotNull(engine.getRepositoryService().createDeploymentQuery().listPage(0, 1));
  211 + DmnEngine dmn = context.getBean(DmnEngine.class);
  212 + assertEquals("oracle", dmn.getDmnEngineConfiguration().getDatabaseType());
  213 + assertFalse(dmn.getDmnEngineConfiguration().isBulkInsertEnabled());
  214 + assertEquals("通过", dmn.getDmnDecisionService().createExecuteDecisionBuilder()
  215 + .decisionKey("dmAutoTwo").variable("amount", 100).executeWithSingleResult().get("result"));
  216 + String model = resourceText("/amount.dmn");
  217 + dmn.getDmnRepositoryService().createDeployment().addString("one.dmn", model)
  218 + .addString("two.dmn", model.replace("dmAmount", "dmAmountTwo")).deploy();
  219 + assertEquals("通过", dmn.getDmnDecisionService().createExecuteDecisionBuilder()
  220 + .decisionKey("dmAmountTwo").variable("amount", 100).executeWithSingleResult().get("result"));
  221 + EventRegistryEngine event = context.getBean(EventRegistryEngine.class);
  222 + assertEquals("oracle", event.getEventRegistryEngineConfiguration().getDatabaseType());
  223 + assertFalse(event.getEventRegistryEngineConfiguration().isBulkInsertEnabled());
  224 + assertTrue(event.getEventRepositoryService().createEventDefinitionQuery().eventDefinitionKey("dmAutoEventOne").count() > 0);
  225 + assertTrue(event.getEventRepositoryService().createEventDefinitionQuery().eventDefinitionKey("dmAutoEventTwo").count() > 0);
  226 + EventDeployment deployment = event.getEventRepositoryService().createDeployment()
  227 + .addString("one.event", "{\"key\":\"dmEventOne\",\"name\":\"One\",\"payload\":[]}")
  228 + .addString("two.event", "{\"key\":\"dmEventTwo\",\"name\":\"Two\",\"payload\":[]}").deploy();
  229 + assertEquals(2, event.getEventRepositoryService().createEventDefinitionQuery().deploymentId(deployment.getId()).count());
  230 + }
  231 + }
  232 +
  233 + private ProcessEngine dmEngine() {
  234 + SpringProcessEngineConfiguration configuration = configuration(dmDataSource());
  235 + configuration.setDatabaseSchemaUpdate("true");
  236 + configureDm(configuration);
  237 + return configuration.buildProcessEngine();
  238 + }
  239 +
  240 + private static DataSource dmDataSource() {
  241 + assumeTrue(System.getenv("DM_JDBC_URL") != null, "设置 DM_JDBC_URL 后执行真实达梦测试");
  242 + return new DriverManagerDataSource(System.getenv("DM_JDBC_URL"),
  243 + System.getenv("DM_JDBC_USER"), System.getenv("DM_JDBC_PASSWORD"));
  244 + }
  245 +
  246 + @Test
  247 + void testDmTransactionRollback() {
  248 + ProcessEngine engine = dmEngine();
  249 + try {
  250 + engine.getRepositoryService().createDeployment().addClasspathResource("approval.bpmn20.xml").deploy();
  251 + String businessKey = UUID.randomUUID().toString();
  252 + SpringProcessEngineConfiguration configuration = (SpringProcessEngineConfiguration) engine.getProcessEngineConfiguration();
  253 + TransactionTemplate transaction = new TransactionTemplate(configuration.getTransactionManager());
  254 + assertThrows(IllegalStateException.class, () -> transaction.execute(status -> {
  255 + engine.getRuntimeService().startProcessInstanceByKey("dmApproval", businessKey);
  256 + throw new IllegalStateException("回滚测试");
  257 + }));
  258 + assertEquals(0, engine.getRuntimeService().createProcessInstanceQuery().processInstanceBusinessKey(businessKey).count());
  259 + assertEquals(0, engine.getHistoryService().createHistoricProcessInstanceQuery().processInstanceBusinessKey(businessKey).count());
  260 + } finally {
  261 + engine.close();
  262 + }
  263 + }
  264 +
  265 + private void configureDm(Object configuration) {
  266 + DmFlowableConfiguration.dmEngineConfigurationBeanPostProcessor().postProcessBeforeInitialization(configuration, "testEngineConfiguration");
  267 + }
  268 +
  269 + private String resourceText(String name) {
  270 + try (InputStream input = getClass().getResourceAsStream(name);
  271 + ByteArrayOutputStream output = new ByteArrayOutputStream()) {
  272 + byte[] buffer = new byte[1024];
  273 + int count;
  274 + while ((count = input.read(buffer)) != -1) {
  275 + output.write(buffer, 0, count);
  276 + }
  277 + return new String(output.toByteArray(), StandardCharsets.UTF_8);
  278 + } catch (java.io.IOException e) {
  279 + throw new IllegalStateException(e);
  280 + }
  281 + }
  282 +
  283 + private SpringProcessEngineConfiguration configuration(DataSource dataSource) {
  284 + SpringProcessEngineConfiguration configuration = new SpringProcessEngineConfiguration();
  285 + configuration.setDataSource(dataSource);
  286 + configuration.setTransactionManager(new DataSourceTransactionManager(dataSource));
  287 + configuration.setAsyncExecutorActivate(false);
  288 + return configuration;
  289 + }
  290 +
  291 + @Configuration(proxyBeanMethods = false)
  292 + @EnableAutoConfiguration
  293 + @Import(DmFlowableConfiguration.class)
  294 + static class TestApplication {
  295 +
  296 + @Bean
  297 + public DataSource dataSource() {
  298 + return dmDataSource();
  299 + }
  300 +
  301 + }
  302 +
  303 +}
sql/dm/flowable-patch-tests/src/test/liquibase/cn/iocoder/yudao/module/bpm/DmDatabaseTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm;
  2 +
  3 +import liquibase.database.DatabaseConnection;
  4 +import liquibase.database.DatabaseFactory;
  5 +import liquibase.database.core.DmDatabase;
  6 +import liquibase.database.core.H2Database;
  7 +import liquibase.database.core.MySQLDatabase;
  8 +import liquibase.database.core.OracleDatabase;
  9 +import liquibase.database.jvm.JdbcConnection;
  10 +import liquibase.datatype.DataTypeFactory;
  11 +import liquibase.datatype.core.BooleanType;
  12 +import org.junit.jupiter.api.AfterEach;
  13 +import org.junit.jupiter.api.Test;
  14 +import org.springframework.jdbc.datasource.DriverManagerDataSource;
  15 +
  16 +import java.lang.reflect.Proxy;
  17 +import java.sql.Connection;
  18 +
  19 +import static org.junit.jupiter.api.Assertions.*;
  20 +import static org.junit.jupiter.api.Assumptions.assumeTrue;
  21 +
  22 +/**
  23 + * Flowable 6.8.0 的达梦 Liquibase SPI 测试
  24 + *
  25 + * @author 芋道源码
  26 + */
  27 +class DmDatabaseTest {
  28 +
  29 + @AfterEach
  30 + void tearDown() {
  31 + DatabaseFactory.reset();
  32 + }
  33 +
  34 + @Test
  35 + void testDriverAndOtherDatabases() throws Exception {
  36 + DmDatabase database = new DmDatabase();
  37 + assertEquals("dm", database.getShortName());
  38 + assertEquals("dm.jdbc.driver.DmDriver", database.getDefaultDriver("jdbc:dm://localhost:5236"));
  39 + assertNull(database.getDefaultDriver(null));
  40 + assertNull(database.getDefaultDriver("jdbc:mysql://localhost/test"));
  41 + assertEquals(5236, database.getDefaultPort());
  42 + DriverManagerDataSource dataSource = new DriverManagerDataSource("jdbc:h2:mem:dm_spi_regression", "sa", "");
  43 + try (Connection connection = dataSource.getConnection()) {
  44 + assertInstanceOf(H2Database.class, DatabaseFactory.getInstance()
  45 + .findCorrectDatabaseImplementation(new JdbcConnection(connection)));
  46 + }
  47 + assertEquals(new BooleanType().toDatabaseDataType(new MySQLDatabase()).toString(),
  48 + DataTypeFactory.getInstance().fromDescription("boolean", new MySQLDatabase())
  49 + .toDatabaseDataType(new MySQLDatabase()).toString());
  50 + }
  51 +
  52 + @Test
  53 + void testOracleAndDmRegistrationOrder() throws Exception {
  54 + for (boolean dmFirst : new boolean[]{true, false}) {
  55 + DatabaseFactory factory = DatabaseFactory.getInstance();
  56 + factory.clearRegistry();
  57 + factory.register(dmFirst ? new DmDatabase() : new OracleDatabase());
  58 + factory.register(dmFirst ? new OracleDatabase() : new DmDatabase());
  59 + assertInstanceOf(DmDatabase.class, factory.findCorrectDatabaseImplementation(metadata("DM DBMS")));
  60 + assertEquals(OracleDatabase.class, factory.findCorrectDatabaseImplementation(metadata("Oracle")).getClass());
  61 + }
  62 + }
  63 +
  64 + @Test
  65 + void testDmMetadataAndBooleanType() throws Exception {
  66 + assumeTrue(System.getenv("DM_JDBC_URL") != null, "设置 DM_JDBC_URL 后执行真实达梦测试");
  67 + DriverManagerDataSource dataSource = new DriverManagerDataSource(System.getenv("DM_JDBC_URL"),
  68 + System.getenv("DM_JDBC_USER"), System.getenv("DM_JDBC_PASSWORD"));
  69 + try (Connection connection = dataSource.getConnection()) {
  70 + liquibase.database.Database database = DatabaseFactory.getInstance()
  71 + .findCorrectDatabaseImplementation(new JdbcConnection(connection));
  72 + assertInstanceOf(DmDatabase.class, database);
  73 + assertEquals("NUMBER(1)", DataTypeFactory.getInstance().fromDescription("boolean", database)
  74 + .toDatabaseDataType(database).toString());
  75 + }
  76 + }
  77 +
  78 + private DatabaseConnection metadata(String product) {
  79 + return (DatabaseConnection) Proxy.newProxyInstance(getClass().getClassLoader(),
  80 + new Class[]{DatabaseConnection.class}, (proxy, method, arguments) -> {
  81 + if ("getDatabaseProductName".equals(method.getName())) return product;
  82 + if ("getConnectionUserName".equals(method.getName())) return "TEST_USER";
  83 + if ("getURL".equals(method.getName())) return "DM DBMS".equals(product) ? "jdbc:dm://test" : "jdbc:oracle:thin:@test";
  84 + if (method.getReturnType() == int.class) return 8;
  85 + if (method.getReturnType() == boolean.class) return false;
  86 + return null;
  87 + });
  88 + }
  89 +
  90 +}
sql/dm/flowable-patch-tests/src/test/resources/amount.dmn 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<definitions xmlns="https://www.omg.org/spec/DMN/20191111/MODEL/"
  3 + id="dmRules" name="达梦决策测试" namespace="http://www.iocoder.cn/dm-test">
  4 + <decision id="dmAmount" name="金额审核">
  5 + <decisionTable id="amountTable" hitPolicy="FIRST">
  6 + <input id="inputAmount"><inputExpression id="amountExpression" typeRef="number"><text>amount</text></inputExpression></input>
  7 + <output id="outputResult" name="result" typeRef="string"/>
  8 + <rule id="accepted">
  9 + <inputEntry id="amountCondition"><text>&gt;= 0</text></inputEntry>
  10 + <outputEntry id="resultValue"><text>"通过"</text></outputEntry>
  11 + </rule>
  12 + </decisionTable>
  13 + </decision>
  14 +</definitions>
sql/dm/flowable-patch-tests/src/test/resources/approval.bpmn20.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
  3 + targetNamespace="http://www.iocoder.cn/dm-test">
  4 + <process id="dmApproval" name="达梦审批回归" isExecutable="true">
  5 + <startEvent id="start"/>
  6 + <userTask id="first" name="审批一"/>
  7 + <userTask id="second" name="审批二"/>
  8 + <endEvent id="end"/>
  9 + <sequenceFlow id="f1" sourceRef="start" targetRef="first"/>
  10 + <sequenceFlow id="f2" sourceRef="first" targetRef="second"/>
  11 + <sequenceFlow id="f3" sourceRef="second" targetRef="end"/>
  12 + </process>
  13 +</definitions>
sql/dm/flowable-patch-tests/src/test/resources/dmn/auto.dmn 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<definitions xmlns="https://www.omg.org/spec/DMN/20191111/MODEL/"
  3 + id="autoRules" name="自动部署测试" namespace="http://www.iocoder.cn/dm-test">
  4 + <decision id="dmAutoOne" name="自动决策一">
  5 + <decisionTable id="tableOne" hitPolicy="FIRST">
  6 + <input id="inputOne"><inputExpression id="expressionOne" typeRef="number"><text>amount</text></inputExpression></input>
  7 + <output id="outputOne" name="result" typeRef="string"/>
  8 + <rule id="ruleOne">
  9 + <inputEntry id="conditionOne"><text>&gt;= 0</text></inputEntry>
  10 + <outputEntry id="valueOne"><text>"通过"</text></outputEntry>
  11 + </rule>
  12 + </decisionTable>
  13 + </decision>
  14 + <decision id="dmAutoTwo" name="自动决策二">
  15 + <decisionTable id="tableTwo" hitPolicy="FIRST">
  16 + <input id="inputTwo"><inputExpression id="expressionTwo" typeRef="number"><text>amount</text></inputExpression></input>
  17 + <output id="outputTwo" name="result" typeRef="string"/>
  18 + <rule id="ruleTwo">
  19 + <inputEntry id="conditionTwo"><text>&gt;= 0</text></inputEntry>
  20 + <outputEntry id="valueTwo"><text>"通过"</text></outputEntry>
  21 + </rule>
  22 + </decisionTable>
  23 + </decision>
  24 +</definitions>
sql/dm/flowable-patch-tests/src/test/resources/eventregistry/one.event 0 → 100644
  1 +{"key":"dmAutoEventOne","name":"自动事件一","payload":[]}
sql/dm/flowable-patch-tests/src/test/resources/eventregistry/two.event 0 → 100644
  1 +{"key":"dmAutoEventTwo","name":"自动事件二","payload":[]}
sql/dm/flowable-patch-tests/src/test/resources/logback-test.xml 0 → 100644
  1 +<configuration>
  2 + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
  3 + <encoder><pattern>%level %logger{40} - %msg%n</pattern></encoder>
  4 + </appender>
  5 + <root level="WARN"><appender-ref ref="STDOUT"/></root>
  6 +</configuration>
sql/dm/flowable-patch-tests/src/test/resources/parallel.bpmn20.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
  3 + targetNamespace="http://www.iocoder.cn/dm-test">
  4 + <process id="dmParallel" isExecutable="true">
  5 + <startEvent id="start"/>
  6 + <parallelGateway id="fork"/>
  7 + <userTask id="left" name="并行审批一"/>
  8 + <userTask id="right" name="并行审批二"/>
  9 + <parallelGateway id="join"/>
  10 + <endEvent id="end"/>
  11 + <sequenceFlow id="f1" sourceRef="start" targetRef="fork"/>
  12 + <sequenceFlow id="f2" sourceRef="fork" targetRef="left"/>
  13 + <sequenceFlow id="f3" sourceRef="fork" targetRef="right"/>
  14 + <sequenceFlow id="f4" sourceRef="left" targetRef="join"/>
  15 + <sequenceFlow id="f5" sourceRef="right" targetRef="join"/>
  16 + <sequenceFlow id="f6" sourceRef="join" targetRef="end"/>
  17 + </process>
  18 +</definitions>
sql/dm/flowable-patch-tests/src/test/resources/timer.bpmn20.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
  3 + targetNamespace="http://www.iocoder.cn/dm-test">
  4 + <process id="dmTimer" isExecutable="true">
  5 + <startEvent id="start"/>
  6 + <intermediateCatchEvent id="wait">
  7 + <timerEventDefinition><timeDuration>P1D</timeDuration></timerEventDefinition>
  8 + </intermediateCatchEvent>
  9 + <userTask id="approval" name="定时后审批"/>
  10 + <endEvent id="end"/>
  11 + <sequenceFlow id="f1" sourceRef="start" targetRef="wait"/>
  12 + <sequenceFlow id="f2" sourceRef="wait" targetRef="approval"/>
  13 + <sequenceFlow id="f3" sourceRef="approval" targetRef="end"/>
  14 + </process>
  15 +</definitions>
sql/dm/flowable-patch/src/main/java/liquibase/database/core/DmDatabase.java deleted
1 -package liquibase.database.core;  
2 -  
3 -import java.lang.reflect.Method;  
4 -import java.sql.Connection;  
5 -import java.sql.ResultSet;  
6 -import java.sql.SQLException;  
7 -import java.sql.Statement;  
8 -import java.util.ArrayList;  
9 -import java.util.Arrays;  
10 -import java.util.HashSet;  
11 -import java.util.List;  
12 -import java.util.Locale;  
13 -import java.util.Map;  
14 -import java.util.Properties;  
15 -import java.util.Set;  
16 -import java.util.regex.Matcher;  
17 -import java.util.regex.Pattern;  
18 -import liquibase.CatalogAndSchema;  
19 -import liquibase.Scope;  
20 -import liquibase.database.AbstractJdbcDatabase;  
21 -import liquibase.database.DatabaseConnection;  
22 -import liquibase.database.OfflineConnection;  
23 -import liquibase.database.jvm.JdbcConnection;  
24 -import liquibase.exception.DatabaseException;  
25 -import liquibase.exception.UnexpectedLiquibaseException;  
26 -import liquibase.exception.ValidationErrors;  
27 -import liquibase.executor.ExecutorService;  
28 -import liquibase.statement.DatabaseFunction;  
29 -import liquibase.statement.SequenceCurrentValueFunction;  
30 -import liquibase.statement.SequenceNextValueFunction;  
31 -import liquibase.statement.core.RawCallStatement;  
32 -import liquibase.statement.core.RawSqlStatement;  
33 -import liquibase.structure.DatabaseObject;  
34 -import liquibase.structure.core.Catalog;  
35 -import liquibase.structure.core.Index;  
36 -import liquibase.structure.core.PrimaryKey;  
37 -import liquibase.structure.core.Schema;  
38 -import liquibase.util.JdbcUtils;  
39 -import liquibase.util.StringUtil;  
40 -  
41 -public class DmDatabase extends AbstractJdbcDatabase {  
42 - private static final String PRODUCT_NAME = "DM DBMS";  
43 -  
44 - @Override  
45 - protected String getDefaultDatabaseProductName() {  
46 - return PRODUCT_NAME;  
47 - }  
48 -  
49 - /**  
50 - * Is this AbstractDatabase subclass the correct one to use for the given connection.  
51 - *  
52 - * @param conn  
53 - */  
54 - @Override  
55 - public boolean isCorrectDatabaseImplementation(DatabaseConnection conn) throws DatabaseException {  
56 - return PRODUCT_NAME.equalsIgnoreCase(conn.getDatabaseProductName());  
57 - }  
58 -  
59 - /**  
60 - * If this database understands the given url, return the default driver class name. Otherwise return null.  
61 - *  
62 - * @param url  
63 - */  
64 - @Override  
65 - public String getDefaultDriver(String url) {  
66 - if(url.startsWith("jdbc:dm")) {  
67 - return "dm.jdbc.driver.DmDriver";  
68 - }  
69 -  
70 - return null;  
71 - }  
72 -  
73 - /**  
74 - * Returns an all-lower-case short name of the product. Used for end-user selecting of database type  
75 - * such as the DBMS precondition.  
76 - */  
77 - @Override  
78 - public String getShortName() {  
79 - return "dm";  
80 - }  
81 -  
82 - @Override  
83 - public Integer getDefaultPort() {  
84 - return 5236;  
85 - }  
86 -  
87 - /**  
88 - * Returns whether this database support initially deferrable columns.  
89 - */  
90 - @Override  
91 - public boolean supportsInitiallyDeferrableColumns() {  
92 - return true;  
93 - }  
94 -  
95 - @Override  
96 - public boolean supportsTablespaces() {  
97 - return true;  
98 - }  
99 -  
100 - @Override  
101 - public int getPriority() {  
102 - return PRIORITY_DEFAULT;  
103 - }  
104 -  
105 - private static final Pattern PROXY_USER = Pattern.compile(".*(?:thin|oci)\\:(.+)/@.*");  
106 -  
107 - protected final int SHORT_IDENTIFIERS_LENGTH = 30;  
108 - protected final int LONG_IDENTIFIERS_LEGNTH = 128;  
109 - public static final int ORACLE_12C_MAJOR_VERSION = 12;  
110 -  
111 - private Set<String> reservedWords = new HashSet<>();  
112 - private Set<String> userDefinedTypes;  
113 - private Map<String, String> savedSessionNlsSettings;  
114 -  
115 - private Boolean canAccessDbaRecycleBin;  
116 - private Integer databaseMajorVersion;  
117 - private Integer databaseMinorVersion;  
118 -  
119 - /**  
120 - * Default constructor for an object that represents the Oracle Database DBMS.  
121 - */  
122 - public DmDatabase() {  
123 - super.unquotedObjectsAreUppercased = true;  
124 - //noinspection HardCodedStringLiteral  
125 - super.setCurrentDateTimeFunction("SYSTIMESTAMP");  
126 - // Setting list of Oracle's native functions  
127 - //noinspection HardCodedStringLiteral  
128 - dateFunctions.add(new DatabaseFunction("SYSDATE"));  
129 - //noinspection HardCodedStringLiteral  
130 - dateFunctions.add(new DatabaseFunction("SYSTIMESTAMP"));  
131 - //noinspection HardCodedStringLiteral  
132 - dateFunctions.add(new DatabaseFunction("CURRENT_TIMESTAMP"));  
133 - //noinspection HardCodedStringLiteral  
134 - super.sequenceNextValueFunction = "%s.nextval";  
135 - //noinspection HardCodedStringLiteral  
136 - super.sequenceCurrentValueFunction = "%s.currval";  
137 - }  
138 -  
139 - private void tryProxySession(final String url, final Connection con) {  
140 - Matcher m = PROXY_USER.matcher(url);  
141 - if (m.matches()) {  
142 - Properties props = new Properties();  
143 - props.put("PROXY_USER_NAME", m.group(1));  
144 - try {  
145 - Method method = con.getClass().getMethod("openProxySession", int.class, Properties.class);  
146 - method.setAccessible(true);  
147 - method.invoke(con, 1, props);  
148 - } catch (Exception e) {  
149 - Scope.getCurrentScope().getLog(getClass()).info("Could not open proxy session on OracleDatabase: " + e.getCause().getMessage());  
150 - }  
151 - }  
152 - }  
153 -  
154 - @Override  
155 - public int getDatabaseMajorVersion() throws DatabaseException {  
156 - if (databaseMajorVersion == null) {  
157 - return super.getDatabaseMajorVersion();  
158 - } else {  
159 - return databaseMajorVersion;  
160 - }  
161 - }  
162 -  
163 - @Override  
164 - public int getDatabaseMinorVersion() throws DatabaseException {  
165 - if (databaseMinorVersion == null) {  
166 - return super.getDatabaseMinorVersion();  
167 - } else {  
168 - return databaseMinorVersion;  
169 - }  
170 - }  
171 -  
172 - @Override  
173 - public String getJdbcCatalogName(CatalogAndSchema schema) {  
174 - return null;  
175 - }  
176 -  
177 - @Override  
178 - public String getJdbcSchemaName(CatalogAndSchema schema) {  
179 - return correctObjectName((schema.getCatalogName() == null) ? schema.getSchemaName() : schema.getCatalogName(), Schema.class);  
180 - }  
181 -  
182 - @Override  
183 - protected String getAutoIncrementClause(final String generationType, final Boolean defaultOnNull) {  
184 - if (StringUtil.isEmpty(generationType)) {  
185 - return super.getAutoIncrementClause();  
186 - }  
187 -  
188 - String autoIncrementClause = "GENERATED %s AS IDENTITY"; // %s -- [ ALWAYS | BY DEFAULT [ ON NULL ] ]  
189 - String generationStrategy = generationType;  
190 - if (Boolean.TRUE.equals(defaultOnNull) && generationType.toUpperCase().equals("BY DEFAULT")) {  
191 - generationStrategy += " ON NULL";  
192 - }  
193 - return String.format(autoIncrementClause, generationStrategy);  
194 - }  
195 -  
196 - @Override  
197 - public String generatePrimaryKeyName(String tableName) {  
198 - if (tableName.length() > 27) {  
199 - //noinspection HardCodedStringLiteral  
200 - return "PK_" + tableName.toUpperCase(Locale.US).substring(0, 27);  
201 - } else {  
202 - //noinspection HardCodedStringLiteral  
203 - return "PK_" + tableName.toUpperCase(Locale.US);  
204 - }  
205 - }  
206 -  
207 - @Override  
208 - public boolean isReservedWord(String objectName) {  
209 - return reservedWords.contains(objectName.toUpperCase());  
210 - }  
211 -  
212 - @Override  
213 - public boolean supportsSequences() {  
214 - return true;  
215 - }  
216 -  
217 - /**  
218 - * Oracle supports catalogs in liquibase terms  
219 - *  
220 - * @return false  
221 - */  
222 - @Override  
223 - public boolean supportsSchemas() {  
224 - return false;  
225 - }  
226 -  
227 - @Override  
228 - protected String getConnectionCatalogName() throws DatabaseException {  
229 - if (getConnection() instanceof OfflineConnection) {  
230 - return getConnection().getCatalog();  
231 - }  
232 - try {  
233 - //noinspection HardCodedStringLiteral  
234 - return Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForObject(new RawCallStatement("select sys_context( 'userenv', 'current_schema' ) from dual"), String.class);  
235 - } catch (Exception e) {  
236 - //noinspection HardCodedStringLiteral  
237 - Scope.getCurrentScope().getLog(getClass()).info("Error getting default schema", e);  
238 - }  
239 - return null;  
240 - }  
241 -  
242 - @Override  
243 - public String getDefaultCatalogName() {//NOPMD  
244 - return (super.getDefaultCatalogName() == null) ? null : super.getDefaultCatalogName().toUpperCase(Locale.US);  
245 - }  
246 -  
247 - /**  
248 - * <p>Returns an Oracle date literal with the same value as a string formatted using ISO 8601.</p>  
249 - *  
250 - * <p>Convert an ISO8601 date string to one of the following results:  
251 - * to_date('1995-05-23', 'YYYY-MM-DD')  
252 - * to_date('1995-05-23 09:23:59', 'YYYY-MM-DD HH24:MI:SS')</p>  
253 - * <p>  
254 - * Implementation restriction:<br>  
255 - * Currently, only the following subsets of ISO8601 are supported:<br>  
256 - * <ul>  
257 - * <li>YYYY-MM-DD</li>  
258 - * <li>YYYY-MM-DDThh:mm:ss</li>  
259 - * </ul>  
260 - */  
261 - @Override  
262 - public String getDateLiteral(String isoDate) {  
263 - String normalLiteral = super.getDateLiteral(isoDate);  
264 -  
265 - if (isDateOnly(isoDate)) {  
266 - return "TO_DATE(" + normalLiteral + ", 'YYYY-MM-DD')";  
267 - } else if (isTimeOnly(isoDate)) {  
268 - return "TO_DATE(" + normalLiteral + ", 'HH24:MI:SS')";  
269 - } else if (isTimestamp(isoDate)) {  
270 - return "TO_TIMESTAMP(" + normalLiteral + ", 'YYYY-MM-DD HH24:MI:SS.FF')";  
271 - } else if (isDateTime(isoDate)) {  
272 - int seppos = normalLiteral.lastIndexOf('.');  
273 - if (seppos != -1) {  
274 - normalLiteral = normalLiteral.substring(0, seppos) + "'";  
275 - }  
276 - return "TO_DATE(" + normalLiteral + ", 'YYYY-MM-DD HH24:MI:SS')";  
277 - }  
278 - return "UNSUPPORTED:" + isoDate;  
279 - }  
280 -  
281 - @Override  
282 - public boolean isSystemObject(DatabaseObject example) {  
283 - if (example == null) {  
284 - return false;  
285 - }  
286 -  
287 - if (this.isLiquibaseObject(example)) {  
288 - return false;  
289 - }  
290 -  
291 - if (example instanceof Schema) {  
292 - //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral  
293 - if ("SYSTEM".equals(example.getName()) || "SYS".equals(example.getName()) || "CTXSYS".equals(example.getName()) || "XDB".equals(example.getName())) {  
294 - return true;  
295 - }  
296 - //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral  
297 - if ("SYSTEM".equals(example.getSchema().getCatalogName()) || "SYS".equals(example.getSchema().getCatalogName()) || "CTXSYS".equals(example.getSchema().getCatalogName()) || "XDB".equals(example.getSchema().getCatalogName())) {  
298 - return true;  
299 - }  
300 - } else if (isSystemObject(example.getSchema())) {  
301 - return true;  
302 - }  
303 - if (example instanceof Catalog) {  
304 - //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral  
305 - if (("SYSTEM".equals(example.getName()) || "SYS".equals(example.getName()) || "CTXSYS".equals(example.getName()) || "XDB".equals(example.getName()))) {  
306 - return true;  
307 - }  
308 - } else if (example.getName() != null) {  
309 - //noinspection HardCodedStringLiteral  
310 - if (example.getName().startsWith("BIN$")) { //oracle deleted table  
311 - boolean filteredInOriginalQuery = this.canAccessDbaRecycleBin();  
312 - if (!filteredInOriginalQuery) {  
313 - filteredInOriginalQuery = StringUtil.trimToEmpty(example.getSchema().getName()).equalsIgnoreCase(this.getConnection().getConnectionUserName());  
314 - }  
315 -  
316 - if (filteredInOriginalQuery) {  
317 - return !((example instanceof PrimaryKey) || (example instanceof Index) || (example instanceof  
318 - liquibase.statement.UniqueConstraint));  
319 - } else {  
320 - return true;  
321 - }  
322 - } else //noinspection HardCodedStringLiteral  
323 - if (example.getName().startsWith("AQ$")) { //oracle AQ tables  
324 - return true;  
325 - } else //noinspection HardCodedStringLiteral  
326 - if (example.getName().startsWith("DR$")) { //oracle index tables  
327 - return true;  
328 - } else //noinspection HardCodedStringLiteral  
329 - if (example.getName().startsWith("SYS_IOT_OVER")) { //oracle system table  
330 - return true;  
331 - } else //noinspection HardCodedStringLiteral,HardCodedStringLiteral  
332 - if ((example.getName().startsWith("MDRT_") || example.getName().startsWith("MDRS_")) && example.getName().endsWith("$")) {  
333 - // CORE-1768 - Oracle creates these for spatial indices and will remove them when the index is removed.  
334 - return true;  
335 - } else //noinspection HardCodedStringLiteral  
336 - if (example.getName().startsWith("MLOG$_")) { //Created by materliaized view logs for every table that is part of a materialized view. Not available for DDL operations.  
337 - return true;  
338 - } else //noinspection HardCodedStringLiteral  
339 - if (example.getName().startsWith("RUPD$_")) { //Created by materialized view log tables using primary keys. Not available for DDL operations.  
340 - return true;  
341 - } else //noinspection HardCodedStringLiteral  
342 - if (example.getName().startsWith("WM$_")) { //Workspace Manager backup tables.  
343 - return true;  
344 - } else //noinspection HardCodedStringLiteral  
345 - if ("CREATE$JAVA$LOB$TABLE".equals(example.getName())) { //This table contains the name of the Java object, the date it was loaded, and has a BLOB column to store the Java object.  
346 - return true;  
347 - } else //noinspection HardCodedStringLiteral  
348 - if ("JAVA$CLASS$MD5$TABLE".equals(example.getName())) { //This is a hash table that tracks the loading of Java objects into a schema.  
349 - return true;  
350 - } else //noinspection HardCodedStringLiteral  
351 - if (example.getName().startsWith("ISEQ$$_")) { //System-generated sequence  
352 - return true;  
353 - } else //noinspection HardCodedStringLiteral  
354 - if (example.getName().startsWith("USLOG$")) { //for update materialized view  
355 - return true;  
356 - } else if (example.getName().startsWith("SYS_FBA")) { //for Flashback tables  
357 - return true;  
358 - }  
359 - }  
360 -  
361 - return super.isSystemObject(example);  
362 - }  
363 -  
364 - @Override  
365 - public boolean supportsAutoIncrement() {  
366 - // Oracle supports Identity beginning with version 12c  
367 - boolean isAutoIncrementSupported = false;  
368 -  
369 - try {  
370 - if (getDatabaseMajorVersion() >= 12) {  
371 - isAutoIncrementSupported = true;  
372 - }  
373 -  
374 - // Returning true will generate create table command with 'IDENTITY' clause, example:  
375 - // CREATE TABLE AutoIncTest (IDPrimaryKey NUMBER(19) GENERATED BY DEFAULT AS IDENTITY NOT NULL, TypeID NUMBER(3) NOT NULL, Description NVARCHAR2(50), CONSTRAINT PK_AutoIncTest PRIMARY KEY (IDPrimaryKey));  
376 -  
377 - // While returning false will continue to generate create table command without 'IDENTITY' clause, example:  
378 - // CREATE TABLE AutoIncTest (IDPrimaryKey NUMBER(19) NOT NULL, TypeID NUMBER(3) NOT NULL, Description NVARCHAR2(50), CONSTRAINT PK_AutoIncTest PRIMARY KEY (IDPrimaryKey));  
379 -  
380 - } catch (DatabaseException ex) {  
381 - isAutoIncrementSupported = false;  
382 - }  
383 -  
384 - return isAutoIncrementSupported;  
385 - }  
386 -  
387 -  
388 -// public Set<UniqueConstraint> findUniqueConstraints(String schema) throws DatabaseException {  
389 -// Set<UniqueConstraint> returnSet = new HashSet<UniqueConstraint>();  
390 -//  
391 -// List<Map> maps = new Executor(this).queryForList(new RawSqlStatement("SELECT UC.CONSTRAINT_NAME, UCC.TABLE_NAME, UCC.COLUMN_NAME FROM USER_CONSTRAINTS UC, USER_CONS_COLUMNS UCC WHERE UC.CONSTRAINT_NAME=UCC.CONSTRAINT_NAME AND CONSTRAINT_TYPE='U' ORDER BY UC.CONSTRAINT_NAME"));  
392 -//  
393 -// UniqueConstraint constraint = null;  
394 -// for (Map map : maps) {  
395 -// if (constraint == null || !constraint.getName().equals(constraint.getName())) {  
396 -// returnSet.add(constraint);  
397 -// Table table = new Table((String) map.get("TABLE_NAME"));  
398 -// constraint = new UniqueConstraint(map.get("CONSTRAINT_NAME").toString(), table);  
399 -// }  
400 -// }  
401 -// if (constraint != null) {  
402 -// returnSet.add(constraint);  
403 -// }  
404 -//  
405 -// return returnSet;  
406 -// }  
407 -  
408 - @Override  
409 - public boolean supportsRestrictForeignKeys() {  
410 - return false;  
411 - }  
412 -  
413 - @Override  
414 - public int getDataTypeMaxParameters(String dataTypeName) {  
415 - //noinspection HardCodedStringLiteral  
416 - if ("BINARY_FLOAT".equals(dataTypeName.toUpperCase())) {  
417 - return 0;  
418 - }  
419 - //noinspection HardCodedStringLiteral  
420 - if ("BINARY_DOUBLE".equals(dataTypeName.toUpperCase())) {  
421 - return 0;  
422 - }  
423 - return super.getDataTypeMaxParameters(dataTypeName);  
424 - }  
425 -  
426 - public String getSystemTableWhereClause(String tableNameColumn) {  
427 - List<String> clauses = new ArrayList<String>(Arrays.asList("BIN$",  
428 - "AQ$",  
429 - "DR$",  
430 - "SYS_IOT_OVER",  
431 - "MLOG$_",  
432 - "RUPD$_",  
433 - "WM$_",  
434 - "ISEQ$$_",  
435 - "USLOG$",  
436 - "SYS_FBA"));  
437 -  
438 - for (int i = 0;i<clauses.size(); i++) {  
439 - clauses.set(i, tableNameColumn+" NOT LIKE '"+clauses.get(i)+"%'");  
440 - }  
441 - return "("+ StringUtil.join(clauses, " AND ") + ")";  
442 - }  
443 -  
444 - @Override  
445 - public boolean jdbcCallsCatalogsSchemas() {  
446 - return true;  
447 - }  
448 -  
449 - public Set<String> getUserDefinedTypes() {  
450 - if (userDefinedTypes == null) {  
451 - userDefinedTypes = new HashSet<>();  
452 - if ((getConnection() != null) && !(getConnection() instanceof OfflineConnection)) {  
453 - try {  
454 - try {  
455 - //noinspection HardCodedStringLiteral  
456 - userDefinedTypes.addAll(Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForList(new RawSqlStatement("SELECT DISTINCT TYPE_NAME FROM ALL_TYPES"), String.class));  
457 - } catch (DatabaseException e) { //fall back to USER_TYPES if the user cannot see ALL_TYPES  
458 - //noinspection HardCodedStringLiteral  
459 - userDefinedTypes.addAll(Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForList(new RawSqlStatement("SELECT TYPE_NAME FROM USER_TYPES"), String.class));  
460 - }  
461 - } catch (DatabaseException e) {  
462 - //ignore error  
463 - }  
464 - }  
465 - }  
466 -  
467 - return userDefinedTypes;  
468 - }  
469 -  
470 - @Override  
471 - public String generateDatabaseFunctionValue(DatabaseFunction databaseFunction) {  
472 - //noinspection HardCodedStringLiteral  
473 - if ((databaseFunction != null) && "current_timestamp".equalsIgnoreCase(databaseFunction.toString())) {  
474 - return databaseFunction.toString();  
475 - }  
476 - if ((databaseFunction instanceof SequenceNextValueFunction) || (databaseFunction instanceof  
477 - SequenceCurrentValueFunction)) {  
478 - String quotedSeq = super.generateDatabaseFunctionValue(databaseFunction);  
479 - // replace "myschema.my_seq".nextval with "myschema"."my_seq".nextval  
480 - return quotedSeq.replaceFirst("\"([^\\.\"]+)\\.([^\\.\"]+)\"", "\"$1\".\"$2\"");  
481 -  
482 - }  
483 -  
484 - return super.generateDatabaseFunctionValue(databaseFunction);  
485 - }  
486 -  
487 - @Override  
488 - public ValidationErrors validate() {  
489 - ValidationErrors errors = super.validate();  
490 - DatabaseConnection connection = getConnection();  
491 - if ((connection == null) || (connection instanceof OfflineConnection)) {  
492 - //noinspection HardCodedStringLiteral  
493 - Scope.getCurrentScope().getLog(getClass()).info("Cannot validate offline database");  
494 - return errors;  
495 - }  
496 -  
497 - if (!canAccessDbaRecycleBin()) {  
498 - errors.addWarning(getDbaRecycleBinWarning());  
499 - }  
500 -  
501 - return errors;  
502 -  
503 - }  
504 -  
505 - public String getDbaRecycleBinWarning() {  
506 - //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,  
507 - // HardCodedStringLiteral  
508 - //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral  
509 - return "Liquibase needs to access the DBA_RECYCLEBIN table so we can automatically handle the case where " +  
510 - "constraints are deleted and restored. Since Oracle doesn't properly restore the original table names " +  
511 - "referenced in the constraint, we use the information from the DBA_RECYCLEBIN to automatically correct this" +  
512 - " issue.\n" +  
513 - "\n" +  
514 - "The user you used to connect to the database (" + getConnection().getConnectionUserName() +  
515 - ") needs to have \"SELECT ON SYS.DBA_RECYCLEBIN\" permissions set before we can perform this operation. " +  
516 - "Please run the following SQL to set the appropriate permissions, and try running the command again.\n" +  
517 - "\n" +  
518 - " GRANT SELECT ON SYS.DBA_RECYCLEBIN TO " + getConnection().getConnectionUserName() + ";";  
519 - }  
520 -  
521 - public boolean canAccessDbaRecycleBin() {  
522 - if (canAccessDbaRecycleBin == null) {  
523 - DatabaseConnection connection = getConnection();  
524 - if ((connection == null) || (connection instanceof OfflineConnection)) {  
525 - return false;  
526 - }  
527 -  
528 - Statement statement = null;  
529 - try {  
530 - statement = ((JdbcConnection) connection).createStatement();  
531 - @SuppressWarnings("HardCodedStringLiteral") ResultSet resultSet = statement.executeQuery("select 1 from dba_recyclebin where 0=1");  
532 - resultSet.close(); //don't need to do anything with the result set, just make sure statement ran.  
533 - this.canAccessDbaRecycleBin = true;  
534 - } catch (Exception e) {  
535 - //noinspection HardCodedStringLiteral  
536 - if ((e instanceof SQLException) && e.getMessage().startsWith("ORA-00942")) { //ORA-00942: table or view does not exist  
537 - this.canAccessDbaRecycleBin = false;  
538 - } else {  
539 - //noinspection HardCodedStringLiteral  
540 - Scope.getCurrentScope().getLog(getClass()).warning("Cannot check dba_recyclebin access", e);  
541 - this.canAccessDbaRecycleBin = false;  
542 - }  
543 - } finally {  
544 - JdbcUtils.close(null, statement);  
545 - }  
546 - }  
547 -  
548 - return canAccessDbaRecycleBin;  
549 - }  
550 -  
551 - @Override  
552 - public boolean supportsNotNullConstraintNames() {  
553 - return true;  
554 - }  
555 -  
556 - /**  
557 - * Tests if the given String would be a valid identifier in Oracle DBMS. In Oracle, a valid identifier has  
558 - * the following form (case-insensitive comparison):  
559 - * 1st character: A-Z  
560 - * 2..n characters: A-Z0-9$_#  
561 - * The maximum length of an identifier differs by Oracle version and object type.  
562 - */  
563 - public boolean isValidOracleIdentifier(String identifier, Class<? extends DatabaseObject> type) {  
564 - if ((identifier == null) || (identifier.length() < 1))  
565 - return false;  
566 -  
567 - if (!identifier.matches("^(i?)[A-Z][A-Z0-9\\$\\_\\#]*$"))  
568 - return false;  
569 -  
570 - /*  
571 - * @todo It seems we currently do not have a class for tablespace identifiers, and all other classes  
572 - * we do know seem to be supported as 12cR2 long identifiers, so:  
573 - */  
574 - return (identifier.length() <= LONG_IDENTIFIERS_LEGNTH);  
575 - }  
576 -  
577 - /**  
578 - * Returns the maximum number of bytes (NOT: characters) for an identifier. For Oracle <=12c Release 20, this  
579 - * is 30 bytes, and starting from 12cR2, up to 128 (except for tablespaces, PDB names and some other rather rare  
580 - * object types).  
581 - *  
582 - * @return the maximum length of an object identifier, in bytes  
583 - */  
584 - public int getIdentifierMaximumLength() {  
585 - try {  
586 - if (getDatabaseMajorVersion() < ORACLE_12C_MAJOR_VERSION) {  
587 - return SHORT_IDENTIFIERS_LENGTH;  
588 - } else if ((getDatabaseMajorVersion() == ORACLE_12C_MAJOR_VERSION) && (getDatabaseMinorVersion() <= 1)) {  
589 - return SHORT_IDENTIFIERS_LENGTH;  
590 - } else {  
591 - return LONG_IDENTIFIERS_LEGNTH;  
592 - }  
593 - } catch (DatabaseException ex) {  
594 - throw new UnexpectedLiquibaseException("Cannot determine the Oracle database version number", ex);  
595 - }  
596 -  
597 - }  
598 -}  
sql/dm/flowable-patch/src/main/java/liquibase/datatype/core/BooleanType.java deleted
1 -package liquibase.datatype.core;  
2 -  
3 -import liquibase.change.core.LoadDataChange;  
4 -import liquibase.database.Database;  
5 -import liquibase.database.core.*;  
6 -import liquibase.datatype.DataTypeInfo;  
7 -import liquibase.datatype.DatabaseDataType;  
8 -import liquibase.datatype.LiquibaseDataType;  
9 -import liquibase.exception.UnexpectedLiquibaseException;  
10 -import liquibase.statement.DatabaseFunction;  
11 -import liquibase.util.StringUtil;  
12 -  
13 -import java.util.Locale;  
14 -import java.util.regex.Pattern;  
15 -  
16 -@DataTypeInfo(name = "boolean", aliases = {"java.sql.Types.BOOLEAN", "java.lang.Boolean", "bit", "bool"}, minParameters = 0, maxParameters = 0, priority = LiquibaseDataType.PRIORITY_DEFAULT)  
17 -public class BooleanType extends LiquibaseDataType {  
18 -  
19 - @Override  
20 - public DatabaseDataType toDatabaseDataType(Database database) {  
21 - String originalDefinition = StringUtil.trimToEmpty(getRawDefinition());  
22 - if ((database instanceof Firebird3Database)) {  
23 - return new DatabaseDataType("BOOLEAN");  
24 - }  
25 -  
26 - if ((database instanceof Db2zDatabase) || (database instanceof FirebirdDatabase)) {  
27 - return new DatabaseDataType("SMALLINT");  
28 - } else if (database instanceof MSSQLDatabase) {  
29 - return new DatabaseDataType(database.escapeDataTypeName("bit"));  
30 - } else if (database instanceof MySQLDatabase) {  
31 - if (originalDefinition.toLowerCase(Locale.US).startsWith("bit")) {  
32 - return new DatabaseDataType("BIT", getParameters());  
33 - }  
34 - return new DatabaseDataType("BIT", 1);  
35 - } else if (database instanceof OracleDatabase) {  
36 - return new DatabaseDataType("NUMBER", 1);  
37 - } else if ((database instanceof SybaseASADatabase) || (database instanceof SybaseDatabase)) {  
38 - return new DatabaseDataType("BIT");  
39 - } else if (database instanceof DerbyDatabase) {  
40 - if (((DerbyDatabase) database).supportsBooleanDataType()) {  
41 - return new DatabaseDataType("BOOLEAN");  
42 - } else {  
43 - return new DatabaseDataType("SMALLINT");  
44 - }  
45 - } else if (database instanceof DB2Database) {  
46 - if (((DB2Database) database).supportsBooleanDataType())  
47 - return new DatabaseDataType("BOOLEAN");  
48 - else  
49 - return new DatabaseDataType("SMALLINT");  
50 - } else if (database instanceof HsqlDatabase) {  
51 - return new DatabaseDataType("BOOLEAN");  
52 - } else if (database instanceof PostgresDatabase) {  
53 - if (originalDefinition.toLowerCase(Locale.US).startsWith("bit")) {  
54 - return new DatabaseDataType("BIT", getParameters());  
55 - }  
56 - } else if (database instanceof DmDatabase) { // dhb52: DM Support  
57 - return new DatabaseDataType("bit");  
58 - }  
59 -  
60 - return super.toDatabaseDataType(database);  
61 - }  
62 -  
63 - @Override  
64 - public String objectToSql(Object value, Database database) {  
65 - if ((value == null) || "null".equals(value.toString().toLowerCase(Locale.US))) {  
66 - return null;  
67 - }  
68 -  
69 - String returnValue;  
70 - if (value instanceof String) {  
71 - value = ((String) value).replaceAll("'", "");  
72 - if ("true".equals(((String) value).toLowerCase(Locale.US)) || "1".equals(value) || "b'1'".equals(((String) value).toLowerCase(Locale.US)) || "t".equals(((String) value).toLowerCase(Locale.US)) || ((String) value).toLowerCase(Locale.US).equals(this.getTrueBooleanValue(database).toLowerCase(Locale.US))) {  
73 - returnValue = this.getTrueBooleanValue(database);  
74 - } else if ("false".equals(((String) value).toLowerCase(Locale.US)) || "0".equals(value) || "b'0'".equals(  
75 - ((String) value).toLowerCase(Locale.US)) || "f".equals(((String) value).toLowerCase(Locale.US)) || ((String) value).toLowerCase(Locale.US).equals(this.getFalseBooleanValue(database).toLowerCase(Locale.US))) {  
76 - returnValue = this.getFalseBooleanValue(database);  
77 - } else if (database instanceof PostgresDatabase && Pattern.matches("b?([01])\\1*(::bit|::\"bit\")?", (String) value)) {  
78 - returnValue = "b'"  
79 - + value.toString()  
80 - .replace("b", "")  
81 - .replace("\"", "")  
82 - .replace("::it", "")  
83 - + "'::\"bit\"";  
84 - } else {  
85 - throw new UnexpectedLiquibaseException("Unknown boolean value: " + value);  
86 - }  
87 - } else if (value instanceof Long) {  
88 - if (Long.valueOf(1).equals(value)) {  
89 - returnValue = this.getTrueBooleanValue(database);  
90 - } else {  
91 - returnValue = this.getFalseBooleanValue(database);  
92 - }  
93 - } else if (value instanceof Number) {  
94 - if (value.equals(1) || "1".equals(value.toString()) || "1.0".equals(value.toString())) {  
95 - returnValue = this.getTrueBooleanValue(database);  
96 - } else {  
97 - returnValue = this.getFalseBooleanValue(database);  
98 - }  
99 - } else if (value instanceof DatabaseFunction) {  
100 - return value.toString();  
101 - } else if (value instanceof Boolean) {  
102 - if (((Boolean) value)) {  
103 - returnValue = this.getTrueBooleanValue(database);  
104 - } else {  
105 - returnValue = this.getFalseBooleanValue(database);  
106 - }  
107 - } else {  
108 - throw new UnexpectedLiquibaseException("Cannot convert type " + value.getClass() + " to a boolean value");  
109 - }  
110 -  
111 - return returnValue;  
112 - }  
113 -  
114 - protected boolean isNumericBoolean(Database database) {  
115 - if (database instanceof Firebird3Database) {  
116 - return false;  
117 - }  
118 - if (database instanceof DerbyDatabase) {  
119 - return !((DerbyDatabase) database).supportsBooleanDataType();  
120 - } else if (database instanceof DB2Database) {  
121 - return !((DB2Database) database).supportsBooleanDataType();  
122 - }  
123 - return (database instanceof Db2zDatabase)  
124 - || (database instanceof FirebirdDatabase)  
125 - || (database instanceof MSSQLDatabase)  
126 - || (database instanceof MySQLDatabase)  
127 - || (database instanceof OracleDatabase)  
128 - || (database instanceof SQLiteDatabase)  
129 - || (database instanceof SybaseASADatabase)  
130 - || (database instanceof SybaseDatabase)  
131 - || (database instanceof DmDatabase); // dhb52: DM Support  
132 - }  
133 -  
134 - /**  
135 - * The database-specific value to use for "false" "boolean" columns.  
136 - */  
137 - public String getFalseBooleanValue(Database database) {  
138 - if (isNumericBoolean(database)) {  
139 - return "0";  
140 - }  
141 - if (database instanceof InformixDatabase) {  
142 - return "'f'";  
143 - }  
144 - return "FALSE";  
145 - }  
146 -  
147 - /**  
148 - * The database-specific value to use for "true" "boolean" columns.  
149 - */  
150 - public String getTrueBooleanValue(Database database) {  
151 - if (isNumericBoolean(database)) {  
152 - return "1";  
153 - }  
154 - if (database instanceof InformixDatabase) {  
155 - return "'t'";  
156 - }  
157 - return "TRUE";  
158 - }  
159 -  
160 - @Override  
161 - public LoadDataChange.LOAD_DATA_TYPE getLoadTypeName() {  
162 - return LoadDataChange.LOAD_DATA_TYPE.BOOLEAN;  
163 - }  
164 -  
165 -}  
sql/dm/flowable-patch/src/main/java/org/flowable/common/engine/impl/AbstractEngineConfiguration.java deleted
1 -/* Licensed under the Apache License, Version 2.0 (the "License");  
2 - * you may not use this file except in compliance with the License.  
3 - * You may obtain a copy of the License at  
4 - *  
5 - * http://www.apache.org/licenses/LICENSE-2.0  
6 - *  
7 - * Unless required by applicable law or agreed to in writing, software  
8 - * distributed under the License is distributed on an "AS IS" BASIS,  
9 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
10 - * See the License for the specific language governing permissions and  
11 - * limitations under the License.  
12 - */  
13 -package org.flowable.common.engine.impl;  
14 -  
15 -import java.io.InputStream;  
16 -import java.io.InputStreamReader;  
17 -import java.io.Reader;  
18 -import java.sql.Connection;  
19 -import java.sql.DatabaseMetaData;  
20 -import java.sql.PreparedStatement;  
21 -import java.sql.ResultSet;  
22 -import java.sql.SQLException;  
23 -import java.time.Duration;  
24 -import java.util.ArrayList;  
25 -import java.util.Collection;  
26 -import java.util.Collections;  
27 -import java.util.Comparator;  
28 -import java.util.HashMap;  
29 -import java.util.List;  
30 -import java.util.Map;  
31 -import java.util.Properties;  
32 -import java.util.ServiceLoader;  
33 -import java.util.Set;  
34 -  
35 -import javax.naming.InitialContext;  
36 -import javax.sql.DataSource;  
37 -  
38 -import org.apache.commons.lang3.StringUtils;  
39 -import org.apache.ibatis.builder.xml.XMLConfigBuilder;  
40 -import org.apache.ibatis.builder.xml.XMLMapperBuilder;  
41 -import org.apache.ibatis.datasource.pooled.PooledDataSource;  
42 -import org.apache.ibatis.mapping.Environment;  
43 -import org.apache.ibatis.plugin.Interceptor;  
44 -import org.apache.ibatis.session.Configuration;  
45 -import org.apache.ibatis.session.SqlSessionFactory;  
46 -import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;  
47 -import org.apache.ibatis.transaction.TransactionFactory;  
48 -import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;  
49 -import org.apache.ibatis.transaction.managed.ManagedTransactionFactory;  
50 -import org.apache.ibatis.type.ArrayTypeHandler;  
51 -import org.apache.ibatis.type.BigDecimalTypeHandler;  
52 -import org.apache.ibatis.type.BlobInputStreamTypeHandler;  
53 -import org.apache.ibatis.type.BlobTypeHandler;  
54 -import org.apache.ibatis.type.BooleanTypeHandler;  
55 -import org.apache.ibatis.type.ByteTypeHandler;  
56 -import org.apache.ibatis.type.ClobTypeHandler;  
57 -import org.apache.ibatis.type.DateOnlyTypeHandler;  
58 -import org.apache.ibatis.type.DateTypeHandler;  
59 -import org.apache.ibatis.type.DoubleTypeHandler;  
60 -import org.apache.ibatis.type.FloatTypeHandler;  
61 -import org.apache.ibatis.type.IntegerTypeHandler;  
62 -import org.apache.ibatis.type.JdbcType;  
63 -import org.apache.ibatis.type.LongTypeHandler;  
64 -import org.apache.ibatis.type.NClobTypeHandler;  
65 -import org.apache.ibatis.type.NStringTypeHandler;  
66 -import org.apache.ibatis.type.ShortTypeHandler;  
67 -import org.apache.ibatis.type.SqlxmlTypeHandler;  
68 -import org.apache.ibatis.type.StringTypeHandler;  
69 -import org.apache.ibatis.type.TimeOnlyTypeHandler;  
70 -import org.apache.ibatis.type.TypeHandlerRegistry;  
71 -import org.flowable.common.engine.api.FlowableException;  
72 -import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;  
73 -import org.flowable.common.engine.api.delegate.event.FlowableEventDispatcher;  
74 -import org.flowable.common.engine.api.delegate.event.FlowableEventListener;  
75 -import org.flowable.common.engine.api.engine.EngineLifecycleListener;  
76 -import org.flowable.common.engine.impl.agenda.AgendaOperationRunner;  
77 -import org.flowable.common.engine.impl.cfg.CommandExecutorImpl;  
78 -import org.flowable.common.engine.impl.cfg.IdGenerator;  
79 -import org.flowable.common.engine.impl.cfg.TransactionContextFactory;  
80 -import org.flowable.common.engine.impl.cfg.standalone.StandaloneMybatisTransactionContextFactory;  
81 -import org.flowable.common.engine.impl.db.CommonDbSchemaManager;  
82 -import org.flowable.common.engine.impl.db.DbSqlSessionFactory;  
83 -import org.flowable.common.engine.impl.db.LogSqlExecutionTimePlugin;  
84 -import org.flowable.common.engine.impl.db.MybatisTypeAliasConfigurator;  
85 -import org.flowable.common.engine.impl.db.MybatisTypeHandlerConfigurator;  
86 -import org.flowable.common.engine.impl.db.SchemaManager;  
87 -import org.flowable.common.engine.impl.event.EventDispatchAction;  
88 -import org.flowable.common.engine.impl.event.FlowableEventDispatcherImpl;  
89 -import org.flowable.common.engine.impl.interceptor.Command;  
90 -import org.flowable.common.engine.impl.interceptor.CommandConfig;  
91 -import org.flowable.common.engine.impl.interceptor.CommandContextFactory;  
92 -import org.flowable.common.engine.impl.interceptor.CommandContextInterceptor;  
93 -import org.flowable.common.engine.impl.interceptor.CommandExecutor;  
94 -import org.flowable.common.engine.impl.interceptor.CommandInterceptor;  
95 -import org.flowable.common.engine.impl.interceptor.CrDbRetryInterceptor;  
96 -import org.flowable.common.engine.impl.interceptor.DefaultCommandInvoker;  
97 -import org.flowable.common.engine.impl.interceptor.LogInterceptor;  
98 -import org.flowable.common.engine.impl.interceptor.SessionFactory;  
99 -import org.flowable.common.engine.impl.interceptor.TransactionContextInterceptor;  
100 -import org.flowable.common.engine.impl.lock.LockManager;  
101 -import org.flowable.common.engine.impl.lock.LockManagerImpl;  
102 -import org.flowable.common.engine.impl.logging.LoggingListener;  
103 -import org.flowable.common.engine.impl.logging.LoggingSession;  
104 -import org.flowable.common.engine.impl.logging.LoggingSessionFactory;  
105 -import org.flowable.common.engine.impl.persistence.GenericManagerFactory;  
106 -import org.flowable.common.engine.impl.persistence.StrongUuidGenerator;  
107 -import org.flowable.common.engine.impl.persistence.cache.EntityCache;  
108 -import org.flowable.common.engine.impl.persistence.cache.EntityCacheImpl;  
109 -import org.flowable.common.engine.impl.persistence.entity.ByteArrayEntityManager;  
110 -import org.flowable.common.engine.impl.persistence.entity.ByteArrayEntityManagerImpl;  
111 -import org.flowable.common.engine.impl.persistence.entity.Entity;  
112 -import org.flowable.common.engine.impl.persistence.entity.PropertyEntityManager;  
113 -import org.flowable.common.engine.impl.persistence.entity.PropertyEntityManagerImpl;  
114 -import org.flowable.common.engine.impl.persistence.entity.TableDataManager;  
115 -import org.flowable.common.engine.impl.persistence.entity.TableDataManagerImpl;  
116 -import org.flowable.common.engine.impl.persistence.entity.data.ByteArrayDataManager;  
117 -import org.flowable.common.engine.impl.persistence.entity.data.PropertyDataManager;  
118 -import org.flowable.common.engine.impl.persistence.entity.data.impl.MybatisByteArrayDataManager;  
119 -import org.flowable.common.engine.impl.persistence.entity.data.impl.MybatisPropertyDataManager;  
120 -import org.flowable.common.engine.impl.runtime.Clock;  
121 -import org.flowable.common.engine.impl.service.CommonEngineServiceImpl;  
122 -import org.flowable.common.engine.impl.util.DefaultClockImpl;  
123 -import org.flowable.common.engine.impl.util.IoUtil;  
124 -import org.flowable.common.engine.impl.util.ReflectUtil;  
125 -import org.flowable.eventregistry.api.EventRegistryEventConsumer;  
126 -import org.slf4j.Logger;  
127 -import org.slf4j.LoggerFactory;  
128 -  
129 -import com.fasterxml.jackson.databind.ObjectMapper;  
130 -import com.fasterxml.jackson.databind.SerializationFeature;  
131 -  
132 -public abstract class AbstractEngineConfiguration {  
133 -  
134 - protected final Logger logger = LoggerFactory.getLogger(getClass());  
135 -  
136 - /** The tenant id indicating 'no tenant' */  
137 - public static final String NO_TENANT_ID = "";  
138 -  
139 - /**  
140 - * Checks the version of the DB schema against the library when the form engine is being created and throws an exception if the versions don't match.  
141 - */  
142 - public static final String DB_SCHEMA_UPDATE_FALSE = "false";  
143 - public static final String DB_SCHEMA_UPDATE_CREATE = "create";  
144 - public static final String DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop";  
145 -  
146 - /**  
147 - * Creates the schema when the form engine is being created and drops the schema when the form engine is being closed.  
148 - */  
149 - public static final String DB_SCHEMA_UPDATE_DROP_CREATE = "drop-create";  
150 -  
151 - /**  
152 - * Upon building of the process engine, a check is performed and an update of the schema is performed if it is necessary.  
153 - */  
154 - public static final String DB_SCHEMA_UPDATE_TRUE = "true";  
155 -  
156 - protected boolean forceCloseMybatisConnectionPool = true;  
157 -  
158 - protected String databaseType;  
159 - protected String jdbcDriver = "org.h2.Driver";  
160 - protected String jdbcUrl = "jdbc:h2:tcp://localhost/~/flowable";  
161 - protected String jdbcUsername = "sa";  
162 - protected String jdbcPassword = "";  
163 - protected String dataSourceJndiName;  
164 - protected int jdbcMaxActiveConnections = 16;  
165 - protected int jdbcMaxIdleConnections = 8;  
166 - protected int jdbcMaxCheckoutTime;  
167 - protected int jdbcMaxWaitTime;  
168 - protected boolean jdbcPingEnabled;  
169 - protected String jdbcPingQuery;  
170 - protected int jdbcPingConnectionNotUsedFor;  
171 - protected int jdbcDefaultTransactionIsolationLevel;  
172 - protected DataSource dataSource;  
173 - protected SchemaManager commonSchemaManager;  
174 - protected SchemaManager schemaManager;  
175 - protected Command<Void> schemaManagementCmd;  
176 -  
177 - protected String databaseSchemaUpdate = DB_SCHEMA_UPDATE_FALSE;  
178 -  
179 - /**  
180 - * Whether to use a lock when performing the database schema create or update operations.  
181 - */  
182 - protected boolean useLockForDatabaseSchemaUpdate = false;  
183 -  
184 - protected String xmlEncoding = "UTF-8";  
185 -  
186 - // COMMAND EXECUTORS ///////////////////////////////////////////////  
187 -  
188 - protected CommandExecutor commandExecutor;  
189 - protected Collection<? extends CommandInterceptor> defaultCommandInterceptors;  
190 - protected CommandConfig defaultCommandConfig;  
191 - protected CommandConfig schemaCommandConfig;  
192 - protected CommandContextFactory commandContextFactory;  
193 - protected CommandInterceptor commandInvoker;  
194 -  
195 - protected AgendaOperationRunner agendaOperationRunner = (commandContext, runnable) -> runnable.run();  
196 -  
197 - protected List<CommandInterceptor> customPreCommandInterceptors;  
198 - protected List<CommandInterceptor> customPostCommandInterceptors;  
199 - protected List<CommandInterceptor> commandInterceptors;  
200 -  
201 - protected Map<String, AbstractEngineConfiguration> engineConfigurations = new HashMap<>();  
202 - protected Map<String, AbstractServiceConfiguration> serviceConfigurations = new HashMap<>();  
203 -  
204 - protected ClassLoader classLoader;  
205 - /**  
206 - * Either use Class.forName or ClassLoader.loadClass for class loading. See http://forums.activiti.org/content/reflectutilloadclass-and-custom- classloader  
207 - */  
208 - protected boolean useClassForNameClassLoading = true;  
209 -  
210 - protected List<EngineLifecycleListener> engineLifecycleListeners;  
211 -  
212 - // Event Registry //////////////////////////////////////////////////  
213 - protected Map<String, EventRegistryEventConsumer> eventRegistryEventConsumers = new HashMap<>();  
214 -  
215 - // MYBATIS SQL SESSION FACTORY /////////////////////////////////////  
216 -  
217 - protected boolean isDbHistoryUsed = true;  
218 - protected DbSqlSessionFactory dbSqlSessionFactory;  
219 - protected SqlSessionFactory sqlSessionFactory;  
220 - protected TransactionFactory transactionFactory;  
221 - protected TransactionContextFactory transactionContextFactory;  
222 -  
223 - /**  
224 - * If set to true, enables bulk insert (grouping sql inserts together). Default true.  
225 - * For some databases (eg DB2+z/OS) needs to be set to false.  
226 - */  
227 - protected boolean isBulkInsertEnabled = true;  
228 -  
229 - /**  
230 - * Some databases have a limit of how many parameters one sql insert can have (eg SQL Server, 2000 params (!= insert statements) ). Tweak this parameter in case of exceptions indicating too much  
231 - * is being put into one bulk insert, or make it higher if your database can cope with it and there are inserts with a huge amount of data.  
232 - * <p>  
233 - * By default: 100 (55 for mssql server as it has a hard limit of 2000 parameters in a statement)  
234 - */  
235 - protected int maxNrOfStatementsInBulkInsert = 100;  
236 -  
237 - public int DEFAULT_MAX_NR_OF_STATEMENTS_BULK_INSERT_SQL_SERVER = 55; // currently Execution has most params (35). 2000 / 35 = 57.  
238 -  
239 - protected String mybatisMappingFile;  
240 - protected Set<Class<?>> customMybatisMappers;  
241 - protected Set<String> customMybatisXMLMappers;  
242 - protected List<Interceptor> customMybatisInterceptors;  
243 -  
244 - protected Set<String> dependentEngineMyBatisXmlMappers;  
245 - protected List<MybatisTypeAliasConfigurator> dependentEngineMybatisTypeAliasConfigs;  
246 - protected List<MybatisTypeHandlerConfigurator> dependentEngineMybatisTypeHandlerConfigs;  
247 -  
248 - // SESSION FACTORIES ///////////////////////////////////////////////  
249 - protected List<SessionFactory> customSessionFactories;  
250 - protected Map<Class<?>, SessionFactory> sessionFactories;  
251 -  
252 - protected boolean enableEventDispatcher = true;  
253 - protected FlowableEventDispatcher eventDispatcher;  
254 - protected List<FlowableEventListener> eventListeners;  
255 - protected Map<String, List<FlowableEventListener>> typedEventListeners;  
256 - protected List<EventDispatchAction> additionalEventDispatchActions;  
257 -  
258 - protected LoggingListener loggingListener;  
259 -  
260 - protected boolean transactionsExternallyManaged;  
261 -  
262 - /**  
263 - * Flag that can be set to configure or not a relational database is used. This is useful for custom implementations that do not use relational databases at all.  
264 - *  
265 - * If true (default), the {@link AbstractEngineConfiguration#getDatabaseSchemaUpdate()} value will be used to determine what needs to happen wrt the database schema.  
266 - *  
267 - * If false, no validation or schema creation will be done. That means that the database schema must have been created 'manually' before but the engine does not validate whether the schema is  
268 - * correct. The {@link AbstractEngineConfiguration#getDatabaseSchemaUpdate()} value will not be used.  
269 - */  
270 - protected boolean usingRelationalDatabase = true;  
271 -  
272 - /**  
273 - * Flag that can be set to configure whether or not a schema is used. This is useful for custom implementations that do not use relational databases at all.  
274 - * Setting {@link #usingRelationalDatabase} to true will automatically imply using a schema.  
275 - */  
276 - protected boolean usingSchemaMgmt = true;  
277 -  
278 - /**  
279 - * Allows configuring a database table prefix which is used for all runtime operations of the process engine. For example, if you specify a prefix named 'PRE1.', Flowable will query for executions  
280 - * in a table named 'PRE1.ACT_RU_EXECUTION_'.  
281 - *  
282 - * <p>  
283 - * <strong>NOTE: the prefix is not respected by automatic database schema management. If you use {@link AbstractEngineConfiguration#DB_SCHEMA_UPDATE_CREATE_DROP} or  
284 - * {@link AbstractEngineConfiguration#DB_SCHEMA_UPDATE_TRUE}, Flowable will create the database tables using the default names, regardless of the prefix configured here.</strong>  
285 - */  
286 - protected String databaseTablePrefix = "";  
287 -  
288 - /**  
289 - * Escape character for doing wildcard searches.  
290 - *  
291 - * This will be added at then end of queries that include for example a LIKE clause. For example: SELECT * FROM table WHERE column LIKE '%\%%' ESCAPE '\';  
292 - */  
293 - protected String databaseWildcardEscapeCharacter;  
294 -  
295 - /**  
296 - * database catalog to use  
297 - */  
298 - protected String databaseCatalog = "";  
299 -  
300 - /**  
301 - * In some situations you want to set the schema to use for table checks / generation if the database metadata doesn't return that correctly, see https://jira.codehaus.org/browse/ACT-1220,  
302 - * https://jira.codehaus.org/browse/ACT-1062  
303 - */  
304 - protected String databaseSchema;  
305 -  
306 - /**  
307 - * Set to true in case the defined databaseTablePrefix is a schema-name, instead of an actual table name prefix. This is relevant for checking if Flowable-tables exist, the databaseTablePrefix  
308 - * will not be used here - since the schema is taken into account already, adding a prefix for the table-check will result in wrong table-names.  
309 - */  
310 - protected boolean tablePrefixIsSchema;  
311 -  
312 - /**  
313 - * Set to true if the latest version of a definition should be retrieved, ignoring a possible parent deployment id value  
314 - */  
315 - protected boolean alwaysLookupLatestDefinitionVersion;  
316 -  
317 - /**  
318 - * Set to true if by default lookups should fallback to the default tenant (an empty string by default or a defined tenant value)  
319 - */  
320 - protected boolean fallbackToDefaultTenant;  
321 -  
322 - /**  
323 - * Default tenant provider that is executed when looking up definitions, in case the global or local fallback to default tenant value is true  
324 - */  
325 - protected DefaultTenantProvider defaultTenantProvider = (tenantId, scope, scopeKey) -> NO_TENANT_ID;  
326 -  
327 - /**  
328 - * Enables the MyBatis plugin that logs the execution time of sql statements.  
329 - */  
330 - protected boolean enableLogSqlExecutionTime;  
331 -  
332 - protected Properties databaseTypeMappings = getDefaultDatabaseTypeMappings();  
333 -  
334 - /**  
335 - * Duration between the checks when acquiring a lock.  
336 - */  
337 - protected Duration lockPollRate = Duration.ofSeconds(10);  
338 -  
339 - /**  
340 - * Duration to wait for the DB Schema lock before giving up.  
341 - */  
342 - protected Duration schemaLockWaitTime = Duration.ofMinutes(5);  
343 -  
344 - // DATA MANAGERS //////////////////////////////////////////////////////////////////  
345 -  
346 - protected PropertyDataManager propertyDataManager;  
347 - protected ByteArrayDataManager byteArrayDataManager;  
348 - protected TableDataManager tableDataManager;  
349 -  
350 - // ENTITY MANAGERS ////////////////////////////////////////////////////////////////  
351 -  
352 - protected PropertyEntityManager propertyEntityManager;  
353 - protected ByteArrayEntityManager byteArrayEntityManager;  
354 -  
355 - protected List<EngineDeployer> customPreDeployers;  
356 - protected List<EngineDeployer> customPostDeployers;  
357 - protected List<EngineDeployer> deployers;  
358 -  
359 - // CONFIGURATORS ////////////////////////////////////////////////////////////  
360 -  
361 - protected boolean enableConfiguratorServiceLoader = true; // Enabled by default. In certain environments this should be set to false (eg osgi)  
362 - protected List<EngineConfigurator> configurators; // The injected configurators  
363 - protected List<EngineConfigurator> allConfigurators; // Including auto-discovered configurators  
364 - protected EngineConfigurator idmEngineConfigurator;  
365 - protected EngineConfigurator eventRegistryConfigurator;  
366 -  
367 - public static final String PRODUCT_NAME_POSTGRES = "PostgreSQL";  
368 - public static final String PRODUCT_NAME_CRDB = "CockroachDB";  
369 -  
370 - public static final String DATABASE_TYPE_H2 = "h2";  
371 - public static final String DATABASE_TYPE_HSQL = "hsql";  
372 - public static final String DATABASE_TYPE_MYSQL = "mysql";  
373 - public static final String DATABASE_TYPE_ORACLE = "oracle";  
374 - public static final String DATABASE_TYPE_POSTGRES = "postgres";  
375 - public static final String DATABASE_TYPE_MSSQL = "mssql";  
376 - public static final String DATABASE_TYPE_DB2 = "db2";  
377 - public static final String DATABASE_TYPE_COCKROACHDB = "cockroachdb";  
378 -  
379 - public static Properties getDefaultDatabaseTypeMappings() {  
380 - Properties databaseTypeMappings = new Properties();  
381 - databaseTypeMappings.setProperty("H2", DATABASE_TYPE_H2);  
382 - databaseTypeMappings.setProperty("HSQL Database Engine", DATABASE_TYPE_HSQL);  
383 - databaseTypeMappings.setProperty("MySQL", DATABASE_TYPE_MYSQL);  
384 - databaseTypeMappings.setProperty("MariaDB", DATABASE_TYPE_MYSQL);  
385 - databaseTypeMappings.setProperty("Oracle", DATABASE_TYPE_ORACLE);  
386 - databaseTypeMappings.setProperty(PRODUCT_NAME_POSTGRES, DATABASE_TYPE_POSTGRES);  
387 - databaseTypeMappings.setProperty("Microsoft SQL Server", DATABASE_TYPE_MSSQL);  
388 - databaseTypeMappings.setProperty(DATABASE_TYPE_DB2, DATABASE_TYPE_DB2);  
389 - databaseTypeMappings.setProperty("DB2", DATABASE_TYPE_DB2);  
390 - databaseTypeMappings.setProperty("DB2/NT", DATABASE_TYPE_DB2);  
391 - databaseTypeMappings.setProperty("DB2/NT64", DATABASE_TYPE_DB2);  
392 - databaseTypeMappings.setProperty("DB2 UDP", DATABASE_TYPE_DB2);  
393 - databaseTypeMappings.setProperty("DB2/LINUX", DATABASE_TYPE_DB2);  
394 - databaseTypeMappings.setProperty("DB2/LINUX390", DATABASE_TYPE_DB2);  
395 - databaseTypeMappings.setProperty("DB2/LINUXX8664", DATABASE_TYPE_DB2);  
396 - databaseTypeMappings.setProperty("DB2/LINUXZ64", DATABASE_TYPE_DB2);  
397 - databaseTypeMappings.setProperty("DB2/LINUXPPC64", DATABASE_TYPE_DB2);  
398 - databaseTypeMappings.setProperty("DB2/LINUXPPC64LE", DATABASE_TYPE_DB2);  
399 - databaseTypeMappings.setProperty("DB2/400 SQL", DATABASE_TYPE_DB2);  
400 - databaseTypeMappings.setProperty("DB2/6000", DATABASE_TYPE_DB2);  
401 - databaseTypeMappings.setProperty("DB2 UDB iSeries", DATABASE_TYPE_DB2);  
402 - databaseTypeMappings.setProperty("DB2/AIX64", DATABASE_TYPE_DB2);  
403 - databaseTypeMappings.setProperty("DB2/HPUX", DATABASE_TYPE_DB2);  
404 - databaseTypeMappings.setProperty("DB2/HP64", DATABASE_TYPE_DB2);  
405 - databaseTypeMappings.setProperty("DB2/SUN", DATABASE_TYPE_DB2);  
406 - databaseTypeMappings.setProperty("DB2/SUN64", DATABASE_TYPE_DB2);  
407 - databaseTypeMappings.setProperty("DB2/PTX", DATABASE_TYPE_DB2);  
408 - databaseTypeMappings.setProperty("DB2/2", DATABASE_TYPE_DB2);  
409 - databaseTypeMappings.setProperty("DB2 UDB AS400", DATABASE_TYPE_DB2);  
410 - databaseTypeMappings.setProperty(PRODUCT_NAME_CRDB, DATABASE_TYPE_COCKROACHDB);  
411 - databaseTypeMappings.setProperty("DM DBMS", DATABASE_TYPE_ORACLE); // dhb52: DM support  
412 - return databaseTypeMappings;  
413 - }  
414 -  
415 - protected Map<Object, Object> beans;  
416 -  
417 - protected IdGenerator idGenerator;  
418 - protected boolean usePrefixId;  
419 -  
420 - protected Clock clock;  
421 - protected ObjectMapper objectMapper;  
422 -  
423 - // Variables  
424 -  
425 - public static final int DEFAULT_GENERIC_MAX_LENGTH_STRING = 4000;  
426 - public static final int DEFAULT_ORACLE_MAX_LENGTH_STRING = 2000;  
427 -  
428 - /**  
429 - * Define a max length for storing String variable types in the database. Mainly used for the Oracle NVARCHAR2 limit of 2000 characters  
430 - */  
431 - protected int maxLengthStringVariableType = -1;  
432 -  
433 - protected void initEngineConfigurations() {  
434 - addEngineConfiguration(getEngineCfgKey(), getEngineScopeType(), this);  
435 - }  
436 -  
437 - // DataSource  
438 - // ///////////////////////////////////////////////////////////////  
439 -  
440 - protected void initDataSource() {  
441 - if (dataSource == null) {  
442 - if (dataSourceJndiName != null) {  
443 - try {  
444 - dataSource = (DataSource) new InitialContext().lookup(dataSourceJndiName);  
445 - } catch (Exception e) {  
446 - throw new FlowableException("couldn't lookup datasource from " + dataSourceJndiName + ": " + e.getMessage(), e);  
447 - }  
448 -  
449 - } else if (jdbcUrl != null) {  
450 - if ((jdbcDriver == null) || (jdbcUsername == null)) {  
451 - throw new FlowableException("DataSource or JDBC properties have to be specified in a process engine configuration");  
452 - }  
453 -  
454 - logger.debug("initializing datasource to db: {}", jdbcUrl);  
455 -  
456 - if (logger.isInfoEnabled()) {  
457 - logger.info("Configuring Datasource with following properties (omitted password for security)");  
458 - logger.info("datasource driver : {}", jdbcDriver);  
459 - logger.info("datasource url : {}", jdbcUrl);  
460 - logger.info("datasource user name : {}", jdbcUsername);  
461 - }  
462 -  
463 - PooledDataSource pooledDataSource = new PooledDataSource(this.getClass().getClassLoader(), jdbcDriver, jdbcUrl, jdbcUsername, jdbcPassword);  
464 -  
465 - if (jdbcMaxActiveConnections > 0) {  
466 - pooledDataSource.setPoolMaximumActiveConnections(jdbcMaxActiveConnections);  
467 - }  
468 - if (jdbcMaxIdleConnections > 0) {  
469 - pooledDataSource.setPoolMaximumIdleConnections(jdbcMaxIdleConnections);  
470 - }  
471 - if (jdbcMaxCheckoutTime > 0) {  
472 - pooledDataSource.setPoolMaximumCheckoutTime(jdbcMaxCheckoutTime);  
473 - }  
474 - if (jdbcMaxWaitTime > 0) {  
475 - pooledDataSource.setPoolTimeToWait(jdbcMaxWaitTime);  
476 - }  
477 - if (jdbcPingEnabled) {  
478 - pooledDataSource.setPoolPingEnabled(true);  
479 - if (jdbcPingQuery != null) {  
480 - pooledDataSource.setPoolPingQuery(jdbcPingQuery);  
481 - }  
482 - pooledDataSource.setPoolPingConnectionsNotUsedFor(jdbcPingConnectionNotUsedFor);  
483 - }  
484 - if (jdbcDefaultTransactionIsolationLevel > 0) {  
485 - pooledDataSource.setDefaultTransactionIsolationLevel(jdbcDefaultTransactionIsolationLevel);  
486 - }  
487 - dataSource = pooledDataSource;  
488 - }  
489 - }  
490 -  
491 - if (databaseType == null) {  
492 - initDatabaseType();  
493 - }  
494 - }  
495 -  
496 - public void initDatabaseType() {  
497 - Connection connection = null;  
498 - try {  
499 - connection = dataSource.getConnection();  
500 - DatabaseMetaData databaseMetaData = connection.getMetaData();  
501 - String databaseProductName = databaseMetaData.getDatabaseProductName();  
502 - logger.debug("database product name: '{}'", databaseProductName);  
503 -  
504 - // CRDB does not expose the version through the jdbc driver, so we need to fetch it through version().  
505 - if (PRODUCT_NAME_POSTGRES.equalsIgnoreCase(databaseProductName)) {  
506 - try (PreparedStatement preparedStatement = connection.prepareStatement("select version() as version;");  
507 - ResultSet resultSet = preparedStatement.executeQuery()) {  
508 - String version = null;  
509 - if (resultSet.next()) {  
510 - version = resultSet.getString("version");  
511 - }  
512 -  
513 - if (StringUtils.isNotEmpty(version) && version.toLowerCase().startsWith(PRODUCT_NAME_CRDB.toLowerCase())) {  
514 - databaseProductName = PRODUCT_NAME_CRDB;  
515 - logger.info("CockroachDB version '{}' detected", version);  
516 - }  
517 - }  
518 - }  
519 -  
520 - databaseType = databaseTypeMappings.getProperty(databaseProductName);  
521 - if (databaseType == null) {  
522 - throw new FlowableException("couldn't deduct database type from database product name '" + databaseProductName + "'");  
523 - }  
524 - logger.debug("using database type: {}", databaseType);  
525 -  
526 - } catch (SQLException e) {  
527 - throw new RuntimeException("Exception while initializing Database connection", e);  
528 - } finally {  
529 - try {  
530 - if (connection != null) {  
531 - connection.close();  
532 - }  
533 - } catch (SQLException e) {  
534 - logger.error("Exception while closing the Database connection", e);  
535 - }  
536 - }  
537 -  
538 - // Special care for MSSQL, as it has a hard limit of 2000 params per statement (incl bulk statement).  
539 - // Especially with executions, with 100 as default, this limit is passed.  
540 - if (DATABASE_TYPE_MSSQL.equals(databaseType)) {  
541 - maxNrOfStatementsInBulkInsert = DEFAULT_MAX_NR_OF_STATEMENTS_BULK_INSERT_SQL_SERVER;  
542 - }  
543 - }  
544 -  
545 - public void initSchemaManager() {  
546 - if (this.commonSchemaManager == null) {  
547 - this.commonSchemaManager = new CommonDbSchemaManager();  
548 - }  
549 - }  
550 -  
551 - // session factories ////////////////////////////////////////////////////////  
552 -  
553 - public void addSessionFactory(SessionFactory sessionFactory) {  
554 - sessionFactories.put(sessionFactory.getSessionType(), sessionFactory);  
555 - }  
556 -  
557 - public void initCommandContextFactory() {  
558 - if (commandContextFactory == null) {  
559 - commandContextFactory = new CommandContextFactory();  
560 - }  
561 - }  
562 -  
563 - public void initTransactionContextFactory() {  
564 - if (transactionContextFactory == null) {  
565 - transactionContextFactory = new StandaloneMybatisTransactionContextFactory();  
566 - }  
567 - }  
568 -  
569 - public void initCommandExecutors() {  
570 - initDefaultCommandConfig();  
571 - initSchemaCommandConfig();  
572 - initCommandInvoker();  
573 - initCommandInterceptors();  
574 - initCommandExecutor();  
575 - }  
576 -  
577 -  
578 - public void initDefaultCommandConfig() {  
579 - if (defaultCommandConfig == null) {  
580 - defaultCommandConfig = new CommandConfig();  
581 - }  
582 - }  
583 -  
584 - public void initSchemaCommandConfig() {  
585 - if (schemaCommandConfig == null) {  
586 - schemaCommandConfig = new CommandConfig();  
587 - }  
588 - }  
589 -  
590 - public void initCommandInvoker() {  
591 - if (commandInvoker == null) {  
592 - commandInvoker = new DefaultCommandInvoker();  
593 - }  
594 - }  
595 -  
596 - public void initCommandInterceptors() {  
597 - if (commandInterceptors == null) {  
598 - commandInterceptors = new ArrayList<>();  
599 - if (customPreCommandInterceptors != null) {  
600 - commandInterceptors.addAll(customPreCommandInterceptors);  
601 - }  
602 - commandInterceptors.addAll(getDefaultCommandInterceptors());  
603 - if (customPostCommandInterceptors != null) {  
604 - commandInterceptors.addAll(customPostCommandInterceptors);  
605 - }  
606 - commandInterceptors.add(commandInvoker);  
607 - }  
608 - }  
609 -  
610 - public Collection<? extends CommandInterceptor> getDefaultCommandInterceptors() {  
611 - if (defaultCommandInterceptors == null) {  
612 - List<CommandInterceptor> interceptors = new ArrayList<>();  
613 - interceptors.add(new LogInterceptor());  
614 -  
615 - if (DATABASE_TYPE_COCKROACHDB.equals(databaseType)) {  
616 - interceptors.add(new CrDbRetryInterceptor());  
617 - }  
618 -  
619 - CommandInterceptor transactionInterceptor = createTransactionInterceptor();  
620 - if (transactionInterceptor != null) {  
621 - interceptors.add(transactionInterceptor);  
622 - }  
623 -  
624 - if (commandContextFactory != null) {  
625 - String engineCfgKey = getEngineCfgKey();  
626 - CommandContextInterceptor commandContextInterceptor = new CommandContextInterceptor(commandContextFactory,  
627 - classLoader, useClassForNameClassLoading, clock, objectMapper);  
628 - engineConfigurations.put(engineCfgKey, this);  
629 - commandContextInterceptor.setEngineCfgKey(engineCfgKey);  
630 - commandContextInterceptor.setEngineConfigurations(engineConfigurations);  
631 - interceptors.add(commandContextInterceptor);  
632 - }  
633 -  
634 - if (transactionContextFactory != null) {  
635 - interceptors.add(new TransactionContextInterceptor(transactionContextFactory));  
636 - }  
637 -  
638 - List<CommandInterceptor> additionalCommandInterceptors = getAdditionalDefaultCommandInterceptors();  
639 - if (additionalCommandInterceptors != null) {  
640 - interceptors.addAll(additionalCommandInterceptors);  
641 - }  
642 -  
643 - defaultCommandInterceptors = interceptors;  
644 - }  
645 - return defaultCommandInterceptors;  
646 - }  
647 -  
648 - public abstract String getEngineCfgKey();  
649 -  
650 - public abstract String getEngineScopeType();  
651 -  
652 - public List<CommandInterceptor> getAdditionalDefaultCommandInterceptors() {  
653 - return null;  
654 - }  
655 -  
656 - public void initCommandExecutor() {  
657 - if (commandExecutor == null) {  
658 - CommandInterceptor first = initInterceptorChain(commandInterceptors);  
659 - commandExecutor = new CommandExecutorImpl(getDefaultCommandConfig(), first);  
660 - }  
661 - }  
662 -  
663 - public CommandInterceptor initInterceptorChain(List<CommandInterceptor> chain) {  
664 - if (chain == null || chain.isEmpty()) {  
665 - throw new FlowableException("invalid command interceptor chain configuration: " + chain);  
666 - }  
667 - for (int i = 0; i < chain.size() - 1; i++) {  
668 - chain.get(i).setNext(chain.get(i + 1));  
669 - }  
670 - return chain.get(0);  
671 - }  
672 -  
673 - public abstract CommandInterceptor createTransactionInterceptor();  
674 -  
675 -  
676 - public void initBeans() {  
677 - if (beans == null) {  
678 - beans = new HashMap<>();  
679 - }  
680 - }  
681 -  
682 - // id generator  
683 - // /////////////////////////////////////////////////////////////  
684 -  
685 - public void initIdGenerator() {  
686 - if (idGenerator == null) {  
687 - idGenerator = new StrongUuidGenerator();  
688 - }  
689 - }  
690 -  
691 - public void initObjectMapper() {  
692 - if (objectMapper == null) {  
693 - objectMapper = new ObjectMapper();  
694 - objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);  
695 - }  
696 - }  
697 -  
698 - public void initClock() {  
699 - if (clock == null) {  
700 - clock = new DefaultClockImpl();  
701 - }  
702 - }  
703 -  
704 - // Data managers ///////////////////////////////////////////////////////////  
705 -  
706 - public void initDataManagers() {  
707 - if (propertyDataManager == null) {  
708 - propertyDataManager = new MybatisPropertyDataManager(idGenerator);  
709 - }  
710 -  
711 - if (byteArrayDataManager == null) {  
712 - byteArrayDataManager = new MybatisByteArrayDataManager(idGenerator);  
713 - }  
714 - }  
715 -  
716 - // Entity managers //////////////////////////////////////////////////////////  
717 -  
718 - public void initEntityManagers() {  
719 - if (propertyEntityManager == null) {  
720 - propertyEntityManager = new PropertyEntityManagerImpl(this, propertyDataManager);  
721 - }  
722 -  
723 - if (byteArrayEntityManager == null) {  
724 - byteArrayEntityManager = new ByteArrayEntityManagerImpl(byteArrayDataManager, getEngineCfgKey(), this::getEventDispatcher);  
725 - }  
726 -  
727 - if (tableDataManager == null) {  
728 - tableDataManager = new TableDataManagerImpl(this);  
729 - }  
730 - }  
731 -  
732 - // services  
733 - // /////////////////////////////////////////////////////////////////  
734 -  
735 - protected void initService(Object service) {  
736 - if (service instanceof CommonEngineServiceImpl) {  
737 - ((CommonEngineServiceImpl) service).setCommandExecutor(commandExecutor);  
738 - }  
739 - }  
740 -  
741 - // myBatis SqlSessionFactory  
742 - // ////////////////////////////////////////////////  
743 -  
744 - public void initSessionFactories() {  
745 - if (sessionFactories == null) {  
746 - sessionFactories = new HashMap<>();  
747 -  
748 - if (usingRelationalDatabase) {  
749 - initDbSqlSessionFactory();  
750 - }  
751 -  
752 - addSessionFactory(new GenericManagerFactory(EntityCache.class, EntityCacheImpl.class));  
753 -  
754 - if (isLoggingSessionEnabled()) {  
755 - if (!sessionFactories.containsKey(LoggingSession.class)) {  
756 - LoggingSessionFactory loggingSessionFactory = new LoggingSessionFactory();  
757 - loggingSessionFactory.setLoggingListener(loggingListener);  
758 - loggingSessionFactory.setObjectMapper(objectMapper);  
759 - sessionFactories.put(LoggingSession.class, loggingSessionFactory);  
760 - }  
761 - }  
762 -  
763 - commandContextFactory.setSessionFactories(sessionFactories);  
764 -  
765 - } else {  
766 - if (usingRelationalDatabase) {  
767 - initDbSqlSessionFactoryEntitySettings();  
768 - }  
769 - }  
770 -  
771 - if (customSessionFactories != null) {  
772 - for (SessionFactory sessionFactory : customSessionFactories) {  
773 - addSessionFactory(sessionFactory);  
774 - }  
775 - }  
776 - }  
777 -  
778 - public void initDbSqlSessionFactory() {  
779 - if (dbSqlSessionFactory == null) {  
780 - dbSqlSessionFactory = createDbSqlSessionFactory();  
781 - }  
782 - dbSqlSessionFactory.setDatabaseType(databaseType);  
783 - dbSqlSessionFactory.setSqlSessionFactory(sqlSessionFactory);  
784 - dbSqlSessionFactory.setDbHistoryUsed(isDbHistoryUsed);  
785 - dbSqlSessionFactory.setDatabaseTablePrefix(databaseTablePrefix);  
786 - dbSqlSessionFactory.setTablePrefixIsSchema(tablePrefixIsSchema);  
787 - dbSqlSessionFactory.setDatabaseCatalog(databaseCatalog);  
788 - dbSqlSessionFactory.setDatabaseSchema(databaseSchema);  
789 - dbSqlSessionFactory.setMaxNrOfStatementsInBulkInsert(maxNrOfStatementsInBulkInsert);  
790 -  
791 - initDbSqlSessionFactoryEntitySettings();  
792 -  
793 - addSessionFactory(dbSqlSessionFactory);  
794 - }  
795 -  
796 - public DbSqlSessionFactory createDbSqlSessionFactory() {  
797 - return new DbSqlSessionFactory(usePrefixId);  
798 - }  
799 -  
800 - protected abstract void initDbSqlSessionFactoryEntitySettings();  
801 -  
802 - protected void defaultInitDbSqlSessionFactoryEntitySettings(List<Class<? extends Entity>> insertOrder, List<Class<? extends Entity>> deleteOrder) {  
803 - if (insertOrder != null) {  
804 - for (Class<? extends Entity> clazz : insertOrder) {  
805 - dbSqlSessionFactory.getInsertionOrder().add(clazz);  
806 -  
807 - if (isBulkInsertEnabled) {  
808 - dbSqlSessionFactory.getBulkInserteableEntityClasses().add(clazz);  
809 - }  
810 - }  
811 - }  
812 -  
813 - if (deleteOrder != null) {  
814 - for (Class<? extends Entity> clazz : deleteOrder) {  
815 - dbSqlSessionFactory.getDeletionOrder().add(clazz);  
816 - }  
817 - }  
818 - }  
819 -  
820 - public void initTransactionFactory() {  
821 - if (transactionFactory == null) {  
822 - if (transactionsExternallyManaged) {  
823 - transactionFactory = new ManagedTransactionFactory();  
824 - Properties properties = new Properties();  
825 - properties.put("closeConnection", "false");  
826 - this.transactionFactory.setProperties(properties);  
827 - } else {  
828 - transactionFactory = new JdbcTransactionFactory();  
829 - }  
830 - }  
831 - }  
832 -  
833 - public void initSqlSessionFactory() {  
834 - if (sqlSessionFactory == null) {  
835 - InputStream inputStream = null;  
836 - try {  
837 - inputStream = getMyBatisXmlConfigurationStream();  
838 -  
839 - Environment environment = new Environment("default", transactionFactory, dataSource);  
840 - Reader reader = new InputStreamReader(inputStream);  
841 - Properties properties = new Properties();  
842 - properties.put("prefix", databaseTablePrefix);  
843 -  
844 - String wildcardEscapeClause = "";  
845 - if ((databaseWildcardEscapeCharacter != null) && (databaseWildcardEscapeCharacter.length() != 0)) {  
846 - wildcardEscapeClause = " escape '" + databaseWildcardEscapeCharacter + "'";  
847 - }  
848 - properties.put("wildcardEscapeClause", wildcardEscapeClause);  
849 -  
850 - // set default properties  
851 - properties.put("limitBefore", "");  
852 - properties.put("limitAfter", "");  
853 - properties.put("limitBetween", "");  
854 - properties.put("limitBeforeNativeQuery", "");  
855 - properties.put("limitAfterNativeQuery", "");  
856 - properties.put("blobType", "BLOB");  
857 - properties.put("boolValue", "TRUE");  
858 -  
859 - if (databaseType != null) {  
860 - properties.load(getResourceAsStream(pathToEngineDbProperties()));  
861 - }  
862 -  
863 - Configuration configuration = initMybatisConfiguration(environment, reader, properties);  
864 - sqlSessionFactory = new DefaultSqlSessionFactory(configuration);  
865 -  
866 - } catch (Exception e) {  
867 - throw new FlowableException("Error while building ibatis SqlSessionFactory: " + e.getMessage(), e);  
868 - } finally {  
869 - IoUtil.closeSilently(inputStream);  
870 - }  
871 - } else {  
872 - // This is needed when the SQL Session Factory is created by another engine.  
873 - // When custom XML Mappers are registered with this engine they need to be loaded in the configuration as well  
874 - applyCustomMybatisCustomizations(sqlSessionFactory.getConfiguration());  
875 - }  
876 - }  
877 -  
878 - public String pathToEngineDbProperties() {  
879 - return "org/flowable/common/db/properties/" + databaseType + ".properties";  
880 - }  
881 -  
882 - public Configuration initMybatisConfiguration(Environment environment, Reader reader, Properties properties) {  
883 - XMLConfigBuilder parser = new XMLConfigBuilder(reader, "", properties);  
884 - Configuration configuration = parser.getConfiguration();  
885 -  
886 - if (databaseType != null) {  
887 - configuration.setDatabaseId(databaseType);  
888 - }  
889 -  
890 - configuration.setEnvironment(environment);  
891 -  
892 - initMybatisTypeHandlers(configuration);  
893 - initCustomMybatisInterceptors(configuration);  
894 - if (isEnableLogSqlExecutionTime()) {  
895 - initMyBatisLogSqlExecutionTimePlugin(configuration);  
896 - }  
897 -  
898 - configuration = parseMybatisConfiguration(parser);  
899 - return configuration;  
900 - }  
901 -  
902 - public void initCustomMybatisMappers(Configuration configuration) {  
903 - if (getCustomMybatisMappers() != null) {  
904 - for (Class<?> clazz : getCustomMybatisMappers()) {  
905 - if (!configuration.hasMapper(clazz)) {  
906 - configuration.addMapper(clazz);  
907 - }  
908 - }  
909 - }  
910 - }  
911 -  
912 - public void initMybatisTypeHandlers(Configuration configuration) {  
913 - // When mapping into Map<String, Object> there is currently a problem with MyBatis.  
914 - // It will return objects which are driver specific.  
915 - // Therefore we are registering the mappings between Object.class and the specific jdbc type here.  
916 - // see https://github.com/mybatis/mybatis-3/issues/2216 for more info  
917 - TypeHandlerRegistry handlerRegistry = configuration.getTypeHandlerRegistry();  
918 -  
919 - handlerRegistry.register(Object.class, JdbcType.BOOLEAN, new BooleanTypeHandler());  
920 - handlerRegistry.register(Object.class, JdbcType.BIT, new BooleanTypeHandler());  
921 -  
922 - handlerRegistry.register(Object.class, JdbcType.TINYINT, new ByteTypeHandler());  
923 -  
924 - handlerRegistry.register(Object.class, JdbcType.SMALLINT, new ShortTypeHandler());  
925 -  
926 - handlerRegistry.register(Object.class, JdbcType.INTEGER, new IntegerTypeHandler());  
927 -  
928 - handlerRegistry.register(Object.class, JdbcType.FLOAT, new FloatTypeHandler());  
929 -  
930 - handlerRegistry.register(Object.class, JdbcType.DOUBLE, new DoubleTypeHandler());  
931 -  
932 - handlerRegistry.register(Object.class, JdbcType.CHAR, new StringTypeHandler());  
933 - handlerRegistry.register(Object.class, JdbcType.CLOB, new ClobTypeHandler());  
934 - handlerRegistry.register(Object.class, JdbcType.VARCHAR, new StringTypeHandler());  
935 - handlerRegistry.register(Object.class, JdbcType.LONGVARCHAR, new StringTypeHandler());  
936 - handlerRegistry.register(Object.class, JdbcType.NVARCHAR, new NStringTypeHandler());  
937 - handlerRegistry.register(Object.class, JdbcType.NCHAR, new NStringTypeHandler());  
938 - handlerRegistry.register(Object.class, JdbcType.NCLOB, new NClobTypeHandler());  
939 -  
940 - handlerRegistry.register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler());  
941 -  
942 - handlerRegistry.register(Object.class, JdbcType.BIGINT, new LongTypeHandler());  
943 -  
944 - handlerRegistry.register(Object.class, JdbcType.REAL, new BigDecimalTypeHandler());  
945 - handlerRegistry.register(Object.class, JdbcType.DECIMAL, new BigDecimalTypeHandler());  
946 - handlerRegistry.register(Object.class, JdbcType.NUMERIC, new BigDecimalTypeHandler());  
947 -  
948 - handlerRegistry.register(Object.class, JdbcType.BLOB, new BlobInputStreamTypeHandler());  
949 - handlerRegistry.register(Object.class, JdbcType.LONGVARBINARY, new BlobTypeHandler());  
950 -  
951 - handlerRegistry.register(Object.class, JdbcType.DATE, new DateOnlyTypeHandler());  
952 - handlerRegistry.register(Object.class, JdbcType.TIME, new TimeOnlyTypeHandler());  
953 - handlerRegistry.register(Object.class, JdbcType.TIMESTAMP, new DateTypeHandler());  
954 -  
955 - handlerRegistry.register(Object.class, JdbcType.SQLXML, new SqlxmlTypeHandler());  
956 - }  
957 -  
958 - public void initCustomMybatisInterceptors(Configuration configuration) {  
959 - if (customMybatisInterceptors!=null){  
960 - for (Interceptor interceptor :customMybatisInterceptors){  
961 - configuration.addInterceptor(interceptor);  
962 - }  
963 - }  
964 - }  
965 -  
966 - public void initMyBatisLogSqlExecutionTimePlugin(Configuration configuration) {  
967 - configuration.addInterceptor(new LogSqlExecutionTimePlugin());  
968 - }  
969 -  
970 - public Configuration parseMybatisConfiguration(XMLConfigBuilder parser) {  
971 - Configuration configuration = parser.parse();  
972 -  
973 - applyCustomMybatisCustomizations(configuration);  
974 - return configuration;  
975 - }  
976 -  
977 - protected void applyCustomMybatisCustomizations(Configuration configuration) {  
978 - initCustomMybatisMappers(configuration);  
979 -  
980 - if (dependentEngineMybatisTypeAliasConfigs != null) {  
981 - for (MybatisTypeAliasConfigurator typeAliasConfig : dependentEngineMybatisTypeAliasConfigs) {  
982 - typeAliasConfig.configure(configuration.getTypeAliasRegistry());  
983 - }  
984 - }  
985 - if (dependentEngineMybatisTypeHandlerConfigs != null) {  
986 - for (MybatisTypeHandlerConfigurator typeHandlerConfig : dependentEngineMybatisTypeHandlerConfigs) {  
987 - typeHandlerConfig.configure(configuration.getTypeHandlerRegistry());  
988 - }  
989 - }  
990 -  
991 - parseDependentEngineMybatisXMLMappers(configuration);  
992 - parseCustomMybatisXMLMappers(configuration);  
993 - }  
994 -  
995 - public void parseCustomMybatisXMLMappers(Configuration configuration) {  
996 - if (getCustomMybatisXMLMappers() != null) {  
997 - for (String resource : getCustomMybatisXMLMappers()) {  
998 - parseMybatisXmlMapping(configuration, resource);  
999 - }  
1000 - }  
1001 - }  
1002 -  
1003 - public void parseDependentEngineMybatisXMLMappers(Configuration configuration) {  
1004 - if (getDependentEngineMyBatisXmlMappers() != null) {  
1005 - for (String resource : getDependentEngineMyBatisXmlMappers()) {  
1006 - parseMybatisXmlMapping(configuration, resource);  
1007 - }  
1008 - }  
1009 - }  
1010 -  
1011 - protected void parseMybatisXmlMapping(Configuration configuration, String resource) {  
1012 - // see XMLConfigBuilder.mapperElement()  
1013 - XMLMapperBuilder mapperParser = new XMLMapperBuilder(getResourceAsStream(resource), configuration, resource, configuration.getSqlFragments());  
1014 - mapperParser.parse();  
1015 - }  
1016 -  
1017 - protected InputStream getResourceAsStream(String resource) {  
1018 - ClassLoader classLoader = getClassLoader();  
1019 - if (classLoader != null) {  
1020 - return getClassLoader().getResourceAsStream(resource);  
1021 - } else {  
1022 - return this.getClass().getClassLoader().getResourceAsStream(resource);  
1023 - }  
1024 - }  
1025 -  
1026 - public void setMybatisMappingFile(String file) {  
1027 - this.mybatisMappingFile = file;  
1028 - }  
1029 -  
1030 - public String getMybatisMappingFile() {  
1031 - return mybatisMappingFile;  
1032 - }  
1033 -  
1034 - public abstract InputStream getMyBatisXmlConfigurationStream();  
1035 -  
1036 - public void initConfigurators() {  
1037 -  
1038 - allConfigurators = new ArrayList<>();  
1039 - allConfigurators.addAll(getEngineSpecificEngineConfigurators());  
1040 -  
1041 - // Configurators that are explicitly added to the config  
1042 - if (configurators != null) {  
1043 - allConfigurators.addAll(configurators);  
1044 - }  
1045 -  
1046 - // Auto discovery through ServiceLoader  
1047 - if (enableConfiguratorServiceLoader) {  
1048 - ClassLoader classLoader = getClassLoader();  
1049 - if (classLoader == null) {  
1050 - classLoader = ReflectUtil.getClassLoader();  
1051 - }  
1052 -  
1053 - ServiceLoader<EngineConfigurator> configuratorServiceLoader = ServiceLoader.load(EngineConfigurator.class, classLoader);  
1054 - int nrOfServiceLoadedConfigurators = 0;  
1055 - for (EngineConfigurator configurator : configuratorServiceLoader) {  
1056 - allConfigurators.add(configurator);  
1057 - nrOfServiceLoadedConfigurators++;  
1058 - }  
1059 -  
1060 - if (nrOfServiceLoadedConfigurators > 0) {  
1061 - logger.info("Found {} auto-discoverable Process Engine Configurator{}", nrOfServiceLoadedConfigurators, nrOfServiceLoadedConfigurators > 1 ? "s" : "");  
1062 - }  
1063 -  
1064 - if (!allConfigurators.isEmpty()) {  
1065 -  
1066 - // Order them according to the priorities (useful for dependent  
1067 - // configurator)  
1068 - allConfigurators.sort(new Comparator<EngineConfigurator>() {  
1069 -  
1070 - @Override  
1071 - public int compare(EngineConfigurator configurator1, EngineConfigurator configurator2) {  
1072 - int priority1 = configurator1.getPriority();  
1073 - int priority2 = configurator2.getPriority();  
1074 -  
1075 - if (priority1 < priority2) {  
1076 - return -1;  
1077 - } else if (priority1 > priority2) {  
1078 - return 1;  
1079 - }  
1080 - return 0;  
1081 - }  
1082 - });  
1083 -  
1084 - // Execute the configurators  
1085 - logger.info("Found {} Engine Configurators in total:", allConfigurators.size());  
1086 - for (EngineConfigurator configurator : allConfigurators) {  
1087 - logger.info("{} (priority:{})", configurator.getClass(), configurator.getPriority());  
1088 - }  
1089 -  
1090 - }  
1091 -  
1092 - }  
1093 - }  
1094 -  
1095 - public void close() {  
1096 - if (forceCloseMybatisConnectionPool && dataSource instanceof PooledDataSource) {  
1097 - /*  
1098 - * When the datasource is created by a Flowable engine (i.e. it's an instance of PooledDataSource),  
1099 - * the connection pool needs to be closed when closing the engine.  
1100 - * Note that calling forceCloseAll() multiple times (as is the case when running with multiple engine) is ok.  
1101 - */  
1102 - ((PooledDataSource) dataSource).forceCloseAll();  
1103 - }  
1104 - }  
1105 -  
1106 - protected List<EngineConfigurator> getEngineSpecificEngineConfigurators() {  
1107 - // meant to be overridden if needed  
1108 - return Collections.emptyList();  
1109 - }  
1110 -  
1111 - public void configuratorsBeforeInit() {  
1112 - for (EngineConfigurator configurator : allConfigurators) {  
1113 - logger.info("Executing beforeInit() of {} (priority:{})", configurator.getClass(), configurator.getPriority());  
1114 - configurator.beforeInit(this);  
1115 - }  
1116 - }  
1117 -  
1118 - public void configuratorsAfterInit() {  
1119 - for (EngineConfigurator configurator : allConfigurators) {  
1120 - logger.info("Executing configure() of {} (priority:{})", configurator.getClass(), configurator.getPriority());  
1121 - configurator.configure(this);  
1122 - }  
1123 - }  
1124 -  
1125 - public LockManager getLockManager(String lockName) {  
1126 - return new LockManagerImpl(commandExecutor, lockName, getLockPollRate(), getEngineCfgKey());  
1127 - }  
1128 -  
1129 - // getters and setters  
1130 - // //////////////////////////////////////////////////////  
1131 -  
1132 - public abstract String getEngineName();  
1133 -  
1134 - public ClassLoader getClassLoader() {  
1135 - return classLoader;  
1136 - }  
1137 -  
1138 - public AbstractEngineConfiguration setClassLoader(ClassLoader classLoader) {  
1139 - this.classLoader = classLoader;  
1140 - return this;  
1141 - }  
1142 -  
1143 - public boolean isUseClassForNameClassLoading() {  
1144 - return useClassForNameClassLoading;  
1145 - }  
1146 -  
1147 - public AbstractEngineConfiguration setUseClassForNameClassLoading(boolean useClassForNameClassLoading) {  
1148 - this.useClassForNameClassLoading = useClassForNameClassLoading;  
1149 - return this;  
1150 - }  
1151 -  
1152 - public void addEngineLifecycleListener(EngineLifecycleListener engineLifecycleListener) {  
1153 - if (this.engineLifecycleListeners == null) {  
1154 - this.engineLifecycleListeners = new ArrayList<>();  
1155 - }  
1156 - this.engineLifecycleListeners.add(engineLifecycleListener);  
1157 - }  
1158 -  
1159 - public List<EngineLifecycleListener> getEngineLifecycleListeners() {  
1160 - return engineLifecycleListeners;  
1161 - }  
1162 -  
1163 - public AbstractEngineConfiguration setEngineLifecycleListeners(List<EngineLifecycleListener> engineLifecycleListeners) {  
1164 - this.engineLifecycleListeners = engineLifecycleListeners;  
1165 - return this;  
1166 - }  
1167 -  
1168 - public String getDatabaseType() {  
1169 - return databaseType;  
1170 - }  
1171 -  
1172 - public AbstractEngineConfiguration setDatabaseType(String databaseType) {  
1173 - this.databaseType = databaseType;  
1174 - return this;  
1175 - }  
1176 -  
1177 - public DataSource getDataSource() {  
1178 - return dataSource;  
1179 - }  
1180 -  
1181 - public AbstractEngineConfiguration setDataSource(DataSource dataSource) {  
1182 - this.dataSource = dataSource;  
1183 - return this;  
1184 - }  
1185 -  
1186 - public SchemaManager getSchemaManager() {  
1187 - return schemaManager;  
1188 - }  
1189 -  
1190 - public AbstractEngineConfiguration setSchemaManager(SchemaManager schemaManager) {  
1191 - this.schemaManager = schemaManager;  
1192 - return this;  
1193 - }  
1194 -  
1195 - public SchemaManager getCommonSchemaManager() {  
1196 - return commonSchemaManager;  
1197 - }  
1198 -  
1199 - public AbstractEngineConfiguration setCommonSchemaManager(SchemaManager commonSchemaManager) {  
1200 - this.commonSchemaManager = commonSchemaManager;  
1201 - return this;  
1202 - }  
1203 -  
1204 - public Command<Void> getSchemaManagementCmd() {  
1205 - return schemaManagementCmd;  
1206 - }  
1207 -  
1208 - public AbstractEngineConfiguration setSchemaManagementCmd(Command<Void> schemaManagementCmd) {  
1209 - this.schemaManagementCmd = schemaManagementCmd;  
1210 - return this;  
1211 - }  
1212 -  
1213 - public String getJdbcDriver() {  
1214 - return jdbcDriver;  
1215 - }  
1216 -  
1217 - public AbstractEngineConfiguration setJdbcDriver(String jdbcDriver) {  
1218 - this.jdbcDriver = jdbcDriver;  
1219 - return this;  
1220 - }  
1221 -  
1222 - public String getJdbcUrl() {  
1223 - return jdbcUrl;  
1224 - }  
1225 -  
1226 - public AbstractEngineConfiguration setJdbcUrl(String jdbcUrl) {  
1227 - this.jdbcUrl = jdbcUrl;  
1228 - return this;  
1229 - }  
1230 -  
1231 - public String getJdbcUsername() {  
1232 - return jdbcUsername;  
1233 - }  
1234 -  
1235 - public AbstractEngineConfiguration setJdbcUsername(String jdbcUsername) {  
1236 - this.jdbcUsername = jdbcUsername;  
1237 - return this;  
1238 - }  
1239 -  
1240 - public String getJdbcPassword() {  
1241 - return jdbcPassword;  
1242 - }  
1243 -  
1244 - public AbstractEngineConfiguration setJdbcPassword(String jdbcPassword) {  
1245 - this.jdbcPassword = jdbcPassword;  
1246 - return this;  
1247 - }  
1248 -  
1249 - public int getJdbcMaxActiveConnections() {  
1250 - return jdbcMaxActiveConnections;  
1251 - }  
1252 -  
1253 - public AbstractEngineConfiguration setJdbcMaxActiveConnections(int jdbcMaxActiveConnections) {  
1254 - this.jdbcMaxActiveConnections = jdbcMaxActiveConnections;  
1255 - return this;  
1256 - }  
1257 -  
1258 - public int getJdbcMaxIdleConnections() {  
1259 - return jdbcMaxIdleConnections;  
1260 - }  
1261 -  
1262 - public AbstractEngineConfiguration setJdbcMaxIdleConnections(int jdbcMaxIdleConnections) {  
1263 - this.jdbcMaxIdleConnections = jdbcMaxIdleConnections;  
1264 - return this;  
1265 - }  
1266 -  
1267 - public int getJdbcMaxCheckoutTime() {  
1268 - return jdbcMaxCheckoutTime;  
1269 - }  
1270 -  
1271 - public AbstractEngineConfiguration setJdbcMaxCheckoutTime(int jdbcMaxCheckoutTime) {  
1272 - this.jdbcMaxCheckoutTime = jdbcMaxCheckoutTime;  
1273 - return this;  
1274 - }  
1275 -  
1276 - public int getJdbcMaxWaitTime() {  
1277 - return jdbcMaxWaitTime;  
1278 - }  
1279 -  
1280 - public AbstractEngineConfiguration setJdbcMaxWaitTime(int jdbcMaxWaitTime) {  
1281 - this.jdbcMaxWaitTime = jdbcMaxWaitTime;  
1282 - return this;  
1283 - }  
1284 -  
1285 - public boolean isJdbcPingEnabled() {  
1286 - return jdbcPingEnabled;  
1287 - }  
1288 -  
1289 - public AbstractEngineConfiguration setJdbcPingEnabled(boolean jdbcPingEnabled) {  
1290 - this.jdbcPingEnabled = jdbcPingEnabled;  
1291 - return this;  
1292 - }  
1293 -  
1294 - public int getJdbcPingConnectionNotUsedFor() {  
1295 - return jdbcPingConnectionNotUsedFor;  
1296 - }  
1297 -  
1298 - public AbstractEngineConfiguration setJdbcPingConnectionNotUsedFor(int jdbcPingConnectionNotUsedFor) {  
1299 - this.jdbcPingConnectionNotUsedFor = jdbcPingConnectionNotUsedFor;  
1300 - return this;  
1301 - }  
1302 -  
1303 - public int getJdbcDefaultTransactionIsolationLevel() {  
1304 - return jdbcDefaultTransactionIsolationLevel;  
1305 - }  
1306 -  
1307 - public AbstractEngineConfiguration setJdbcDefaultTransactionIsolationLevel(int jdbcDefaultTransactionIsolationLevel) {  
1308 - this.jdbcDefaultTransactionIsolationLevel = jdbcDefaultTransactionIsolationLevel;  
1309 - return this;  
1310 - }  
1311 -  
1312 - public String getJdbcPingQuery() {  
1313 - return jdbcPingQuery;  
1314 - }  
1315 -  
1316 - public AbstractEngineConfiguration setJdbcPingQuery(String jdbcPingQuery) {  
1317 - this.jdbcPingQuery = jdbcPingQuery;  
1318 - return this;  
1319 - }  
1320 -  
1321 - public String getDataSourceJndiName() {  
1322 - return dataSourceJndiName;  
1323 - }  
1324 -  
1325 - public AbstractEngineConfiguration setDataSourceJndiName(String dataSourceJndiName) {  
1326 - this.dataSourceJndiName = dataSourceJndiName;  
1327 - return this;  
1328 - }  
1329 -  
1330 - public CommandConfig getSchemaCommandConfig() {  
1331 - return schemaCommandConfig;  
1332 - }  
1333 -  
1334 - public AbstractEngineConfiguration setSchemaCommandConfig(CommandConfig schemaCommandConfig) {  
1335 - this.schemaCommandConfig = schemaCommandConfig;  
1336 - return this;  
1337 - }  
1338 -  
1339 - public boolean isTransactionsExternallyManaged() {  
1340 - return transactionsExternallyManaged;  
1341 - }  
1342 -  
1343 - public AbstractEngineConfiguration setTransactionsExternallyManaged(boolean transactionsExternallyManaged) {  
1344 - this.transactionsExternallyManaged = transactionsExternallyManaged;  
1345 - return this;  
1346 - }  
1347 -  
1348 - public Map<Object, Object> getBeans() {  
1349 - return beans;  
1350 - }  
1351 -  
1352 - public AbstractEngineConfiguration setBeans(Map<Object, Object> beans) {  
1353 - this.beans = beans;  
1354 - return this;  
1355 - }  
1356 -  
1357 - public IdGenerator getIdGenerator() {  
1358 - return idGenerator;  
1359 - }  
1360 -  
1361 - public AbstractEngineConfiguration setIdGenerator(IdGenerator idGenerator) {  
1362 - this.idGenerator = idGenerator;  
1363 - return this;  
1364 - }  
1365 -  
1366 - public boolean isUsePrefixId() {  
1367 - return usePrefixId;  
1368 - }  
1369 -  
1370 - public AbstractEngineConfiguration setUsePrefixId(boolean usePrefixId) {  
1371 - this.usePrefixId = usePrefixId;  
1372 - return this;  
1373 - }  
1374 -  
1375 - public String getXmlEncoding() {  
1376 - return xmlEncoding;  
1377 - }  
1378 -  
1379 - public AbstractEngineConfiguration setXmlEncoding(String xmlEncoding) {  
1380 - this.xmlEncoding = xmlEncoding;  
1381 - return this;  
1382 - }  
1383 -  
1384 - public CommandConfig getDefaultCommandConfig() {  
1385 - return defaultCommandConfig;  
1386 - }  
1387 -  
1388 - public AbstractEngineConfiguration setDefaultCommandConfig(CommandConfig defaultCommandConfig) {  
1389 - this.defaultCommandConfig = defaultCommandConfig;  
1390 - return this;  
1391 - }  
1392 -  
1393 - public CommandExecutor getCommandExecutor() {  
1394 - return commandExecutor;  
1395 - }  
1396 -  
1397 - public AbstractEngineConfiguration setCommandExecutor(CommandExecutor commandExecutor) {  
1398 - this.commandExecutor = commandExecutor;  
1399 - return this;  
1400 - }  
1401 -  
1402 - public CommandContextFactory getCommandContextFactory() {  
1403 - return commandContextFactory;  
1404 - }  
1405 -  
1406 - public AbstractEngineConfiguration setCommandContextFactory(CommandContextFactory commandContextFactory) {  
1407 - this.commandContextFactory = commandContextFactory;  
1408 - return this;  
1409 - }  
1410 -  
1411 - public CommandInterceptor getCommandInvoker() {  
1412 - return commandInvoker;  
1413 - }  
1414 -  
1415 - public AbstractEngineConfiguration setCommandInvoker(CommandInterceptor commandInvoker) {  
1416 - this.commandInvoker = commandInvoker;  
1417 - return this;  
1418 - }  
1419 -  
1420 - public AgendaOperationRunner getAgendaOperationRunner() {  
1421 - return agendaOperationRunner;  
1422 - }  
1423 -  
1424 - public AbstractEngineConfiguration setAgendaOperationRunner(AgendaOperationRunner agendaOperationRunner) {  
1425 - this.agendaOperationRunner = agendaOperationRunner;  
1426 - return this;  
1427 - }  
1428 -  
1429 - public List<CommandInterceptor> getCustomPreCommandInterceptors() {  
1430 - return customPreCommandInterceptors;  
1431 - }  
1432 -  
1433 - public AbstractEngineConfiguration setCustomPreCommandInterceptors(List<CommandInterceptor> customPreCommandInterceptors) {  
1434 - this.customPreCommandInterceptors = customPreCommandInterceptors;  
1435 - return this;  
1436 - }  
1437 -  
1438 - public List<CommandInterceptor> getCustomPostCommandInterceptors() {  
1439 - return customPostCommandInterceptors;  
1440 - }  
1441 -  
1442 - public AbstractEngineConfiguration setCustomPostCommandInterceptors(List<CommandInterceptor> customPostCommandInterceptors) {  
1443 - this.customPostCommandInterceptors = customPostCommandInterceptors;  
1444 - return this;  
1445 - }  
1446 -  
1447 - public List<CommandInterceptor> getCommandInterceptors() {  
1448 - return commandInterceptors;  
1449 - }  
1450 -  
1451 - public AbstractEngineConfiguration setCommandInterceptors(List<CommandInterceptor> commandInterceptors) {  
1452 - this.commandInterceptors = commandInterceptors;  
1453 - return this;  
1454 - }  
1455 -  
1456 - public Map<String, AbstractEngineConfiguration> getEngineConfigurations() {  
1457 - return engineConfigurations;  
1458 - }  
1459 -  
1460 - public AbstractEngineConfiguration setEngineConfigurations(Map<String, AbstractEngineConfiguration> engineConfigurations) {  
1461 - this.engineConfigurations = engineConfigurations;  
1462 - return this;  
1463 - }  
1464 -  
1465 - public void addEngineConfiguration(String key, String scopeType, AbstractEngineConfiguration engineConfiguration) {  
1466 - if (engineConfigurations == null) {  
1467 - engineConfigurations = new HashMap<>();  
1468 - }  
1469 - engineConfigurations.put(key, engineConfiguration);  
1470 - engineConfigurations.put(scopeType, engineConfiguration);  
1471 - }  
1472 -  
1473 - public Map<String, AbstractServiceConfiguration> getServiceConfigurations() {  
1474 - return serviceConfigurations;  
1475 - }  
1476 -  
1477 - public AbstractEngineConfiguration setServiceConfigurations(Map<String, AbstractServiceConfiguration> serviceConfigurations) {  
1478 - this.serviceConfigurations = serviceConfigurations;  
1479 - return this;  
1480 - }  
1481 -  
1482 - public void addServiceConfiguration(String key, AbstractServiceConfiguration serviceConfiguration) {  
1483 - if (serviceConfigurations == null) {  
1484 - serviceConfigurations = new HashMap<>();  
1485 - }  
1486 - serviceConfigurations.put(key, serviceConfiguration);  
1487 - }  
1488 -  
1489 - public Map<String, EventRegistryEventConsumer> getEventRegistryEventConsumers() {  
1490 - return eventRegistryEventConsumers;  
1491 - }  
1492 -  
1493 - public AbstractEngineConfiguration setEventRegistryEventConsumers(Map<String, EventRegistryEventConsumer> eventRegistryEventConsumers) {  
1494 - this.eventRegistryEventConsumers = eventRegistryEventConsumers;  
1495 - return this;  
1496 - }  
1497 -  
1498 - public void addEventRegistryEventConsumer(String key, EventRegistryEventConsumer eventRegistryEventConsumer) {  
1499 - if (eventRegistryEventConsumers == null) {  
1500 - eventRegistryEventConsumers = new HashMap<>();  
1501 - }  
1502 - eventRegistryEventConsumers.put(key, eventRegistryEventConsumer);  
1503 - }  
1504 -  
1505 - public AbstractEngineConfiguration setDefaultCommandInterceptors(Collection<? extends CommandInterceptor> defaultCommandInterceptors) {  
1506 - this.defaultCommandInterceptors = defaultCommandInterceptors;  
1507 - return this;  
1508 - }  
1509 -  
1510 - public SqlSessionFactory getSqlSessionFactory() {  
1511 - return sqlSessionFactory;  
1512 - }  
1513 -  
1514 - public AbstractEngineConfiguration setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {  
1515 - this.sqlSessionFactory = sqlSessionFactory;  
1516 - return this;  
1517 - }  
1518 -  
1519 - public boolean isDbHistoryUsed() {  
1520 - return isDbHistoryUsed;  
1521 - }  
1522 -  
1523 - public AbstractEngineConfiguration setDbHistoryUsed(boolean isDbHistoryUsed) {  
1524 - this.isDbHistoryUsed = isDbHistoryUsed;  
1525 - return this;  
1526 - }  
1527 -  
1528 - public DbSqlSessionFactory getDbSqlSessionFactory() {  
1529 - return dbSqlSessionFactory;  
1530 - }  
1531 -  
1532 - public AbstractEngineConfiguration setDbSqlSessionFactory(DbSqlSessionFactory dbSqlSessionFactory) {  
1533 - this.dbSqlSessionFactory = dbSqlSessionFactory;  
1534 - return this;  
1535 - }  
1536 -  
1537 - public TransactionFactory getTransactionFactory() {  
1538 - return transactionFactory;  
1539 - }  
1540 -  
1541 - public AbstractEngineConfiguration setTransactionFactory(TransactionFactory transactionFactory) {  
1542 - this.transactionFactory = transactionFactory;  
1543 - return this;  
1544 - }  
1545 -  
1546 - public TransactionContextFactory getTransactionContextFactory() {  
1547 - return transactionContextFactory;  
1548 - }  
1549 -  
1550 - public AbstractEngineConfiguration setTransactionContextFactory(TransactionContextFactory transactionContextFactory) {  
1551 - this.transactionContextFactory = transactionContextFactory;  
1552 - return this;  
1553 - }  
1554 -  
1555 - public int getMaxNrOfStatementsInBulkInsert() {  
1556 - return maxNrOfStatementsInBulkInsert;  
1557 - }  
1558 -  
1559 - public AbstractEngineConfiguration setMaxNrOfStatementsInBulkInsert(int maxNrOfStatementsInBulkInsert) {  
1560 - this.maxNrOfStatementsInBulkInsert = maxNrOfStatementsInBulkInsert;  
1561 - return this;  
1562 - }  
1563 -  
1564 - public boolean isBulkInsertEnabled() {  
1565 - return isBulkInsertEnabled;  
1566 - }  
1567 -  
1568 - public AbstractEngineConfiguration setBulkInsertEnabled(boolean isBulkInsertEnabled) {  
1569 - this.isBulkInsertEnabled = isBulkInsertEnabled;  
1570 - return this;  
1571 - }  
1572 -  
1573 - public Set<Class<?>> getCustomMybatisMappers() {  
1574 - return customMybatisMappers;  
1575 - }  
1576 -  
1577 - public AbstractEngineConfiguration setCustomMybatisMappers(Set<Class<?>> customMybatisMappers) {  
1578 - this.customMybatisMappers = customMybatisMappers;  
1579 - return this;  
1580 - }  
1581 -  
1582 - public Set<String> getCustomMybatisXMLMappers() {  
1583 - return customMybatisXMLMappers;  
1584 - }  
1585 -  
1586 - public AbstractEngineConfiguration setCustomMybatisXMLMappers(Set<String> customMybatisXMLMappers) {  
1587 - this.customMybatisXMLMappers = customMybatisXMLMappers;  
1588 - return this;  
1589 - }  
1590 -  
1591 - public Set<String> getDependentEngineMyBatisXmlMappers() {  
1592 - return dependentEngineMyBatisXmlMappers;  
1593 - }  
1594 -  
1595 - public AbstractEngineConfiguration setCustomMybatisInterceptors(List<Interceptor> customMybatisInterceptors) {  
1596 - this.customMybatisInterceptors = customMybatisInterceptors;  
1597 - return this;  
1598 - }  
1599 -  
1600 - public List<Interceptor> getCustomMybatisInterceptors() {  
1601 - return customMybatisInterceptors;  
1602 - }  
1603 -  
1604 - public AbstractEngineConfiguration setDependentEngineMyBatisXmlMappers(Set<String> dependentEngineMyBatisXmlMappers) {  
1605 - this.dependentEngineMyBatisXmlMappers = dependentEngineMyBatisXmlMappers;  
1606 - return this;  
1607 - }  
1608 -  
1609 - public List<MybatisTypeAliasConfigurator> getDependentEngineMybatisTypeAliasConfigs() {  
1610 - return dependentEngineMybatisTypeAliasConfigs;  
1611 - }  
1612 -  
1613 - public AbstractEngineConfiguration setDependentEngineMybatisTypeAliasConfigs(List<MybatisTypeAliasConfigurator> dependentEngineMybatisTypeAliasConfigs) {  
1614 - this.dependentEngineMybatisTypeAliasConfigs = dependentEngineMybatisTypeAliasConfigs;  
1615 - return this;  
1616 - }  
1617 -  
1618 - public List<MybatisTypeHandlerConfigurator> getDependentEngineMybatisTypeHandlerConfigs() {  
1619 - return dependentEngineMybatisTypeHandlerConfigs;  
1620 - }  
1621 -  
1622 - public AbstractEngineConfiguration setDependentEngineMybatisTypeHandlerConfigs(List<MybatisTypeHandlerConfigurator> dependentEngineMybatisTypeHandlerConfigs) {  
1623 - this.dependentEngineMybatisTypeHandlerConfigs = dependentEngineMybatisTypeHandlerConfigs;  
1624 - return this;  
1625 - }  
1626 -  
1627 - public List<SessionFactory> getCustomSessionFactories() {  
1628 - return customSessionFactories;  
1629 - }  
1630 -  
1631 - public AbstractEngineConfiguration addCustomSessionFactory(SessionFactory sessionFactory) {  
1632 - if (customSessionFactories == null) {  
1633 - customSessionFactories = new ArrayList<>();  
1634 - }  
1635 - customSessionFactories.add(sessionFactory);  
1636 - return this;  
1637 - }  
1638 -  
1639 - public AbstractEngineConfiguration setCustomSessionFactories(List<SessionFactory> customSessionFactories) {  
1640 - this.customSessionFactories = customSessionFactories;  
1641 - return this;  
1642 - }  
1643 -  
1644 - public boolean isUsingRelationalDatabase() {  
1645 - return usingRelationalDatabase;  
1646 - }  
1647 -  
1648 - public AbstractEngineConfiguration setUsingRelationalDatabase(boolean usingRelationalDatabase) {  
1649 - this.usingRelationalDatabase = usingRelationalDatabase;  
1650 - return this;  
1651 - }  
1652 -  
1653 - public boolean isUsingSchemaMgmt() {  
1654 - return usingSchemaMgmt;  
1655 - }  
1656 -  
1657 - public AbstractEngineConfiguration setUsingSchemaMgmt(boolean usingSchema) {  
1658 - this.usingSchemaMgmt = usingSchema;  
1659 - return this;  
1660 - }  
1661 -  
1662 - public String getDatabaseTablePrefix() {  
1663 - return databaseTablePrefix;  
1664 - }  
1665 -  
1666 - public AbstractEngineConfiguration setDatabaseTablePrefix(String databaseTablePrefix) {  
1667 - this.databaseTablePrefix = databaseTablePrefix;  
1668 - return this;  
1669 - }  
1670 -  
1671 - public String getDatabaseWildcardEscapeCharacter() {  
1672 - return databaseWildcardEscapeCharacter;  
1673 - }  
1674 -  
1675 - public AbstractEngineConfiguration setDatabaseWildcardEscapeCharacter(String databaseWildcardEscapeCharacter) {  
1676 - this.databaseWildcardEscapeCharacter = databaseWildcardEscapeCharacter;  
1677 - return this;  
1678 - }  
1679 -  
1680 - public String getDatabaseCatalog() {  
1681 - return databaseCatalog;  
1682 - }  
1683 -  
1684 - public AbstractEngineConfiguration setDatabaseCatalog(String databaseCatalog) {  
1685 - this.databaseCatalog = databaseCatalog;  
1686 - return this;  
1687 - }  
1688 -  
1689 - public String getDatabaseSchema() {  
1690 - return databaseSchema;  
1691 - }  
1692 -  
1693 - public AbstractEngineConfiguration setDatabaseSchema(String databaseSchema) {  
1694 - this.databaseSchema = databaseSchema;  
1695 - return this;  
1696 - }  
1697 -  
1698 - public boolean isTablePrefixIsSchema() {  
1699 - return tablePrefixIsSchema;  
1700 - }  
1701 -  
1702 - public AbstractEngineConfiguration setTablePrefixIsSchema(boolean tablePrefixIsSchema) {  
1703 - this.tablePrefixIsSchema = tablePrefixIsSchema;  
1704 - return this;  
1705 - }  
1706 -  
1707 - public boolean isAlwaysLookupLatestDefinitionVersion() {  
1708 - return alwaysLookupLatestDefinitionVersion;  
1709 - }  
1710 -  
1711 - public AbstractEngineConfiguration setAlwaysLookupLatestDefinitionVersion(boolean alwaysLookupLatestDefinitionVersion) {  
1712 - this.alwaysLookupLatestDefinitionVersion = alwaysLookupLatestDefinitionVersion;  
1713 - return this;  
1714 - }  
1715 -  
1716 - public boolean isFallbackToDefaultTenant() {  
1717 - return fallbackToDefaultTenant;  
1718 - }  
1719 -  
1720 - public AbstractEngineConfiguration setFallbackToDefaultTenant(boolean fallbackToDefaultTenant) {  
1721 - this.fallbackToDefaultTenant = fallbackToDefaultTenant;  
1722 - return this;  
1723 - }  
1724 -  
1725 - /**  
1726 - * @return name of the default tenant  
1727 - * @deprecated use {@link AbstractEngineConfiguration#getDefaultTenantProvider()} instead  
1728 - */  
1729 - @Deprecated  
1730 - public String getDefaultTenantValue() {  
1731 - return getDefaultTenantProvider().getDefaultTenant(null, null, null);  
1732 - }  
1733 -  
1734 - public AbstractEngineConfiguration setDefaultTenantValue(String defaultTenantValue) {  
1735 - this.defaultTenantProvider = (tenantId, scope, scopeKey) -> defaultTenantValue;  
1736 - return this;  
1737 - }  
1738 -  
1739 - public DefaultTenantProvider getDefaultTenantProvider() {  
1740 - return defaultTenantProvider;  
1741 - }  
1742 -  
1743 - public AbstractEngineConfiguration setDefaultTenantProvider(DefaultTenantProvider defaultTenantProvider) {  
1744 - this.defaultTenantProvider = defaultTenantProvider;  
1745 - return this;  
1746 - }  
1747 -  
1748 - public boolean isEnableLogSqlExecutionTime() {  
1749 - return enableLogSqlExecutionTime;  
1750 - }  
1751 -  
1752 - public void setEnableLogSqlExecutionTime(boolean enableLogSqlExecutionTime) {  
1753 - this.enableLogSqlExecutionTime = enableLogSqlExecutionTime;  
1754 - }  
1755 -  
1756 - public Map<Class<?>, SessionFactory> getSessionFactories() {  
1757 - return sessionFactories;  
1758 - }  
1759 -  
1760 - public AbstractEngineConfiguration setSessionFactories(Map<Class<?>, SessionFactory> sessionFactories) {  
1761 - this.sessionFactories = sessionFactories;  
1762 - return this;  
1763 - }  
1764 -  
1765 - public String getDatabaseSchemaUpdate() {  
1766 - return databaseSchemaUpdate;  
1767 - }  
1768 -  
1769 - public AbstractEngineConfiguration setDatabaseSchemaUpdate(String databaseSchemaUpdate) {  
1770 - this.databaseSchemaUpdate = databaseSchemaUpdate;  
1771 - return this;  
1772 - }  
1773 -  
1774 - public boolean isUseLockForDatabaseSchemaUpdate() {  
1775 - return useLockForDatabaseSchemaUpdate;  
1776 - }  
1777 -  
1778 - public AbstractEngineConfiguration setUseLockForDatabaseSchemaUpdate(boolean useLockForDatabaseSchemaUpdate) {  
1779 - this.useLockForDatabaseSchemaUpdate = useLockForDatabaseSchemaUpdate;  
1780 - return this;  
1781 - }  
1782 -  
1783 - public boolean isEnableEventDispatcher() {  
1784 - return enableEventDispatcher;  
1785 - }  
1786 -  
1787 - public AbstractEngineConfiguration setEnableEventDispatcher(boolean enableEventDispatcher) {  
1788 - this.enableEventDispatcher = enableEventDispatcher;  
1789 - return this;  
1790 - }  
1791 -  
1792 - public FlowableEventDispatcher getEventDispatcher() {  
1793 - return eventDispatcher;  
1794 - }  
1795 -  
1796 - public AbstractEngineConfiguration setEventDispatcher(FlowableEventDispatcher eventDispatcher) {  
1797 - this.eventDispatcher = eventDispatcher;  
1798 - return this;  
1799 - }  
1800 -  
1801 - public List<FlowableEventListener> getEventListeners() {  
1802 - return eventListeners;  
1803 - }  
1804 -  
1805 - public AbstractEngineConfiguration setEventListeners(List<FlowableEventListener> eventListeners) {  
1806 - this.eventListeners = eventListeners;  
1807 - return this;  
1808 - }  
1809 -  
1810 - public Map<String, List<FlowableEventListener>> getTypedEventListeners() {  
1811 - return typedEventListeners;  
1812 - }  
1813 -  
1814 - public AbstractEngineConfiguration setTypedEventListeners(Map<String, List<FlowableEventListener>> typedEventListeners) {  
1815 - this.typedEventListeners = typedEventListeners;  
1816 - return this;  
1817 - }  
1818 -  
1819 - public List<EventDispatchAction> getAdditionalEventDispatchActions() {  
1820 - return additionalEventDispatchActions;  
1821 - }  
1822 -  
1823 - public AbstractEngineConfiguration setAdditionalEventDispatchActions(List<EventDispatchAction> additionalEventDispatchActions) {  
1824 - this.additionalEventDispatchActions = additionalEventDispatchActions;  
1825 - return this;  
1826 - }  
1827 -  
1828 - public void initEventDispatcher() {  
1829 - if (this.eventDispatcher == null) {  
1830 - this.eventDispatcher = new FlowableEventDispatcherImpl();  
1831 - }  
1832 -  
1833 - initAdditionalEventDispatchActions();  
1834 -  
1835 - this.eventDispatcher.setEnabled(enableEventDispatcher);  
1836 -  
1837 - initEventListeners();  
1838 - initTypedEventListeners();  
1839 - }  
1840 -  
1841 - protected void initEventListeners() {  
1842 - if (eventListeners != null) {  
1843 - for (FlowableEventListener listenerToAdd : eventListeners) {  
1844 - this.eventDispatcher.addEventListener(listenerToAdd);  
1845 - }  
1846 - }  
1847 - }  
1848 -  
1849 - protected void initAdditionalEventDispatchActions() {  
1850 - if (this.additionalEventDispatchActions == null) {  
1851 - this.additionalEventDispatchActions = new ArrayList<>();  
1852 - }  
1853 - }  
1854 -  
1855 - protected void initTypedEventListeners() {  
1856 - if (typedEventListeners != null) {  
1857 - for (Map.Entry<String, List<FlowableEventListener>> listenersToAdd : typedEventListeners.entrySet()) {  
1858 - // Extract types from the given string  
1859 - FlowableEngineEventType[] types = FlowableEngineEventType.getTypesFromString(listenersToAdd.getKey());  
1860 -  
1861 - for (FlowableEventListener listenerToAdd : listenersToAdd.getValue()) {  
1862 - this.eventDispatcher.addEventListener(listenerToAdd, types);  
1863 - }  
1864 - }  
1865 - }  
1866 - }  
1867 -  
1868 - public boolean isLoggingSessionEnabled() {  
1869 - return loggingListener != null;  
1870 - }  
1871 -  
1872 - public LoggingListener getLoggingListener() {  
1873 - return loggingListener;  
1874 - }  
1875 -  
1876 - public void setLoggingListener(LoggingListener loggingListener) {  
1877 - this.loggingListener = loggingListener;  
1878 - }  
1879 -  
1880 - public Clock getClock() {  
1881 - return clock;  
1882 - }  
1883 -  
1884 - public AbstractEngineConfiguration setClock(Clock clock) {  
1885 - this.clock = clock;  
1886 - return this;  
1887 - }  
1888 -  
1889 - public ObjectMapper getObjectMapper() {  
1890 - return objectMapper;  
1891 - }  
1892 -  
1893 - public AbstractEngineConfiguration setObjectMapper(ObjectMapper objectMapper) {  
1894 - this.objectMapper = objectMapper;  
1895 - return this;  
1896 - }  
1897 -  
1898 - public int getMaxLengthString() {  
1899 - if (maxLengthStringVariableType == -1) {  
1900 - if ("oracle".equalsIgnoreCase(databaseType)) {  
1901 - return DEFAULT_ORACLE_MAX_LENGTH_STRING;  
1902 - } else {  
1903 - return DEFAULT_GENERIC_MAX_LENGTH_STRING;  
1904 - }  
1905 - } else {  
1906 - return maxLengthStringVariableType;  
1907 - }  
1908 - }  
1909 -  
1910 - public int getMaxLengthStringVariableType() {  
1911 - return maxLengthStringVariableType;  
1912 - }  
1913 -  
1914 - public AbstractEngineConfiguration setMaxLengthStringVariableType(int maxLengthStringVariableType) {  
1915 - this.maxLengthStringVariableType = maxLengthStringVariableType;  
1916 - return this;  
1917 - }  
1918 -  
1919 - public PropertyDataManager getPropertyDataManager() {  
1920 - return propertyDataManager;  
1921 - }  
1922 -  
1923 - public Duration getLockPollRate() {  
1924 - return lockPollRate;  
1925 - }  
1926 -  
1927 - public AbstractEngineConfiguration setLockPollRate(Duration lockPollRate) {  
1928 - this.lockPollRate = lockPollRate;  
1929 - return this;  
1930 - }  
1931 -  
1932 - public Duration getSchemaLockWaitTime() {  
1933 - return schemaLockWaitTime;  
1934 - }  
1935 -  
1936 - public void setSchemaLockWaitTime(Duration schemaLockWaitTime) {  
1937 - this.schemaLockWaitTime = schemaLockWaitTime;  
1938 - }  
1939 -  
1940 - public AbstractEngineConfiguration setPropertyDataManager(PropertyDataManager propertyDataManager) {  
1941 - this.propertyDataManager = propertyDataManager;  
1942 - return this;  
1943 - }  
1944 -  
1945 - public PropertyEntityManager getPropertyEntityManager() {  
1946 - return propertyEntityManager;  
1947 - }  
1948 -  
1949 - public AbstractEngineConfiguration setPropertyEntityManager(PropertyEntityManager propertyEntityManager) {  
1950 - this.propertyEntityManager = propertyEntityManager;  
1951 - return this;  
1952 - }  
1953 -  
1954 - public ByteArrayDataManager getByteArrayDataManager() {  
1955 - return byteArrayDataManager;  
1956 - }  
1957 -  
1958 - public AbstractEngineConfiguration setByteArrayDataManager(ByteArrayDataManager byteArrayDataManager) {  
1959 - this.byteArrayDataManager = byteArrayDataManager;  
1960 - return this;  
1961 - }  
1962 -  
1963 - public ByteArrayEntityManager getByteArrayEntityManager() {  
1964 - return byteArrayEntityManager;  
1965 - }  
1966 -  
1967 - public AbstractEngineConfiguration setByteArrayEntityManager(ByteArrayEntityManager byteArrayEntityManager) {  
1968 - this.byteArrayEntityManager = byteArrayEntityManager;  
1969 - return this;  
1970 - }  
1971 -  
1972 - public TableDataManager getTableDataManager() {  
1973 - return tableDataManager;  
1974 - }  
1975 -  
1976 - public AbstractEngineConfiguration setTableDataManager(TableDataManager tableDataManager) {  
1977 - this.tableDataManager = tableDataManager;  
1978 - return this;  
1979 - }  
1980 -  
1981 - public List<EngineDeployer> getDeployers() {  
1982 - return deployers;  
1983 - }  
1984 -  
1985 - public AbstractEngineConfiguration setDeployers(List<EngineDeployer> deployers) {  
1986 - this.deployers = deployers;  
1987 - return this;  
1988 - }  
1989 -  
1990 - public List<EngineDeployer> getCustomPreDeployers() {  
1991 - return customPreDeployers;  
1992 - }  
1993 -  
1994 - public AbstractEngineConfiguration setCustomPreDeployers(List<EngineDeployer> customPreDeployers) {  
1995 - this.customPreDeployers = customPreDeployers;  
1996 - return this;  
1997 - }  
1998 -  
1999 - public List<EngineDeployer> getCustomPostDeployers() {  
2000 - return customPostDeployers;  
2001 - }  
2002 -  
2003 - public AbstractEngineConfiguration setCustomPostDeployers(List<EngineDeployer> customPostDeployers) {  
2004 - this.customPostDeployers = customPostDeployers;  
2005 - return this;  
2006 - }  
2007 -  
2008 - public boolean isEnableConfiguratorServiceLoader() {  
2009 - return enableConfiguratorServiceLoader;  
2010 - }  
2011 -  
2012 - public AbstractEngineConfiguration setEnableConfiguratorServiceLoader(boolean enableConfiguratorServiceLoader) {  
2013 - this.enableConfiguratorServiceLoader = enableConfiguratorServiceLoader;  
2014 - return this;  
2015 - }  
2016 -  
2017 - public List<EngineConfigurator> getConfigurators() {  
2018 - return configurators;  
2019 - }  
2020 -  
2021 - public AbstractEngineConfiguration addConfigurator(EngineConfigurator configurator) {  
2022 - if (configurators == null) {  
2023 - configurators = new ArrayList<>();  
2024 - }  
2025 - configurators.add(configurator);  
2026 - return this;  
2027 - }  
2028 -  
2029 - /**  
2030 - * @return All {@link EngineConfigurator} instances. Will only contain values after init of the engine.  
2031 - * Use the {@link #getConfigurators()} or {@link #addConfigurator(EngineConfigurator)} methods otherwise.  
2032 - */  
2033 - public List<EngineConfigurator> getAllConfigurators() {  
2034 - return allConfigurators;  
2035 - }  
2036 -  
2037 - public AbstractEngineConfiguration setConfigurators(List<EngineConfigurator> configurators) {  
2038 - this.configurators = configurators;  
2039 - return this;  
2040 - }  
2041 -  
2042 - public EngineConfigurator getIdmEngineConfigurator() {  
2043 - return idmEngineConfigurator;  
2044 - }  
2045 -  
2046 - public AbstractEngineConfiguration setIdmEngineConfigurator(EngineConfigurator idmEngineConfigurator) {  
2047 - this.idmEngineConfigurator = idmEngineConfigurator;  
2048 - return this;  
2049 - }  
2050 -  
2051 - public EngineConfigurator getEventRegistryConfigurator() {  
2052 - return eventRegistryConfigurator;  
2053 - }  
2054 -  
2055 - public AbstractEngineConfiguration setEventRegistryConfigurator(EngineConfigurator eventRegistryConfigurator) {  
2056 - this.eventRegistryConfigurator = eventRegistryConfigurator;  
2057 - return this;  
2058 - }  
2059 -  
2060 - public AbstractEngineConfiguration setForceCloseMybatisConnectionPool(boolean forceCloseMybatisConnectionPool) {  
2061 - this.forceCloseMybatisConnectionPool = forceCloseMybatisConnectionPool;  
2062 - return this;  
2063 - }  
2064 -  
2065 - public boolean isForceCloseMybatisConnectionPool() {  
2066 - return forceCloseMybatisConnectionPool;  
2067 - }  
2068 -}  
sql/dm/flowable-patch/src/main/resources/META-INF/package-info.md deleted
1 -防止IDEA将`.`和`/`混为一谈  
2 \ No newline at end of file 0 \ No newline at end of file
sql/dm/flowable-patch/src/main/resources/META-INF/services/liquibase.database.Database deleted
1 -liquibase.database.core.CockroachDatabase  
2 -liquibase.database.core.DB2Database  
3 -liquibase.database.core.Db2zDatabase  
4 -liquibase.database.core.DerbyDatabase  
5 -liquibase.database.core.Firebird3Database  
6 -liquibase.database.core.FirebirdDatabase  
7 -liquibase.database.core.H2Database  
8 -liquibase.database.core.HsqlDatabase  
9 -liquibase.database.core.InformixDatabase  
10 -liquibase.database.core.Ingres9Database  
11 -liquibase.database.core.MSSQLDatabase  
12 -liquibase.database.core.MariaDBDatabase  
13 -liquibase.database.core.MockDatabase  
14 -liquibase.database.core.MySQLDatabase  
15 -liquibase.database.core.OracleDatabase  
16 -liquibase.database.core.PostgresDatabase  
17 -liquibase.database.core.SQLiteDatabase  
18 -liquibase.database.core.SybaseASADatabase  
19 -liquibase.database.core.SybaseDatabase  
20 -liquibase.database.core.DmDatabase  
21 -liquibase.database.core.UnsupportedDatabase