Commit e04c4b11df95323cd090672b73678346c5edbf68

Authored by dhb52
1 parent e8bc284d

feat: 达梦flowable 6.8适配

sql/dm/flowable-6.8.md 0 → 100644
  1 +# 达梦 flowable 适配
  2 +
  3 +参考文档: [《Flowable6.8(6.x 版本通用)整合集成达梦 8 数据库(DM8)详解,解决自动生成表时 dmn 相关表语法报错问题》](https://blog.csdn.net/TangBoBoa/article/details/130392495)
  4 +
  5 +## 1. 覆盖 flowable,liquibase 相关代码
  6 +
  7 +把`flowable-patch/src`下的文件按文件结果添加到`yudao-server`项目对应目录中
  8 +
  9 +## 2. 修改相关 DAO
  10 +
  11 +例如`cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO`
  12 +
  13 +```diff
  14 +- @TableField("`type`")
  15 +private String type;
  16 +```
  17 +
  18 +## 3. 关于`flowable.database-schema-update`配置
  19 +
  20 +首次运行,修改`flowable.database-schema-update=true`,系统会自动建表,第二次运行需要修改为`false`。
  21 +
  22 +## 4. TODO
  23 +
  24 +配置`flowable.database-schema-update=true`第二次运行失败,报错
  25 +
  26 +```text
  27 +Object [FLW_EV_DATABASECHANGELOG] already exists
  28 +```
... ...
sql/dm/flowable-patch/src/main/java/liquibase/database/core/DmDatabase.java 0 → 100644
  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 0 → 100644
  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 0 → 100644
  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);
  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 0 → 100644
  1 +防止IDEA将`.`和`/`混为一谈
0 2 \ No newline at end of file
... ...
sql/dm/flowable-patch/src/main/resources/META-INF/services/liquibase.database.Database 0 → 100644
  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
... ...