Commit d07869f4614058188b19e69bd3567d34b3fcb5fa
Committed by
Gitee
!723 feat: 达梦flowable 6.8适配
Merge pull request !723 from dhb52/master
Showing
6 changed files
with
2881 additions
and
0 deletions
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`或者`yudao-module-bpm-biz`项目对应目录中,甚至你可以做个独立模块。 | ||
| 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); // dhb52: DM support | ||
| 412 | + return databaseTypeMappings; | ||
| 413 | + } | ||
| 414 | + | ||
| 415 | + protected Map<Object, Object> beans; | ||
| 416 | + | ||
| 417 | + protected IdGenerator idGenerator; | ||
| 418 | + protected boolean usePrefixId; | ||
| 419 | + | ||
| 420 | + protected Clock clock; | ||
| 421 | + protected ObjectMapper objectMapper; | ||
| 422 | + | ||
| 423 | + // Variables | ||
| 424 | + | ||
| 425 | + public static final int DEFAULT_GENERIC_MAX_LENGTH_STRING = 4000; | ||
| 426 | + public static final int DEFAULT_ORACLE_MAX_LENGTH_STRING = 2000; | ||
| 427 | + | ||
| 428 | + /** | ||
| 429 | + * Define a max length for storing String variable types in the database. Mainly used for the Oracle NVARCHAR2 limit of 2000 characters | ||
| 430 | + */ | ||
| 431 | + protected int maxLengthStringVariableType = -1; | ||
| 432 | + | ||
| 433 | + protected void initEngineConfigurations() { | ||
| 434 | + addEngineConfiguration(getEngineCfgKey(), getEngineScopeType(), this); | ||
| 435 | + } | ||
| 436 | + | ||
| 437 | + // DataSource | ||
| 438 | + // /////////////////////////////////////////////////////////////// | ||
| 439 | + | ||
| 440 | + protected void initDataSource() { | ||
| 441 | + if (dataSource == null) { | ||
| 442 | + if (dataSourceJndiName != null) { | ||
| 443 | + try { | ||
| 444 | + dataSource = (DataSource) new InitialContext().lookup(dataSourceJndiName); | ||
| 445 | + } catch (Exception e) { | ||
| 446 | + throw new FlowableException("couldn't lookup datasource from " + dataSourceJndiName + ": " + e.getMessage(), e); | ||
| 447 | + } | ||
| 448 | + | ||
| 449 | + } else if (jdbcUrl != null) { | ||
| 450 | + if ((jdbcDriver == null) || (jdbcUsername == null)) { | ||
| 451 | + throw new FlowableException("DataSource or JDBC properties have to be specified in a process engine configuration"); | ||
| 452 | + } | ||
| 453 | + | ||
| 454 | + logger.debug("initializing datasource to db: {}", jdbcUrl); | ||
| 455 | + | ||
| 456 | + if (logger.isInfoEnabled()) { | ||
| 457 | + logger.info("Configuring Datasource with following properties (omitted password for security)"); | ||
| 458 | + logger.info("datasource driver : {}", jdbcDriver); | ||
| 459 | + logger.info("datasource url : {}", jdbcUrl); | ||
| 460 | + logger.info("datasource user name : {}", jdbcUsername); | ||
| 461 | + } | ||
| 462 | + | ||
| 463 | + PooledDataSource pooledDataSource = new PooledDataSource(this.getClass().getClassLoader(), jdbcDriver, jdbcUrl, jdbcUsername, jdbcPassword); | ||
| 464 | + | ||
| 465 | + if (jdbcMaxActiveConnections > 0) { | ||
| 466 | + pooledDataSource.setPoolMaximumActiveConnections(jdbcMaxActiveConnections); | ||
| 467 | + } | ||
| 468 | + if (jdbcMaxIdleConnections > 0) { | ||
| 469 | + pooledDataSource.setPoolMaximumIdleConnections(jdbcMaxIdleConnections); | ||
| 470 | + } | ||
| 471 | + if (jdbcMaxCheckoutTime > 0) { | ||
| 472 | + pooledDataSource.setPoolMaximumCheckoutTime(jdbcMaxCheckoutTime); | ||
| 473 | + } | ||
| 474 | + if (jdbcMaxWaitTime > 0) { | ||
| 475 | + pooledDataSource.setPoolTimeToWait(jdbcMaxWaitTime); | ||
| 476 | + } | ||
| 477 | + if (jdbcPingEnabled) { | ||
| 478 | + pooledDataSource.setPoolPingEnabled(true); | ||
| 479 | + if (jdbcPingQuery != null) { | ||
| 480 | + pooledDataSource.setPoolPingQuery(jdbcPingQuery); | ||
| 481 | + } | ||
| 482 | + pooledDataSource.setPoolPingConnectionsNotUsedFor(jdbcPingConnectionNotUsedFor); | ||
| 483 | + } | ||
| 484 | + if (jdbcDefaultTransactionIsolationLevel > 0) { | ||
| 485 | + pooledDataSource.setDefaultTransactionIsolationLevel(jdbcDefaultTransactionIsolationLevel); | ||
| 486 | + } | ||
| 487 | + dataSource = pooledDataSource; | ||
| 488 | + } | ||
| 489 | + } | ||
| 490 | + | ||
| 491 | + if (databaseType == null) { | ||
| 492 | + initDatabaseType(); | ||
| 493 | + } | ||
| 494 | + } | ||
| 495 | + | ||
| 496 | + public void initDatabaseType() { | ||
| 497 | + Connection connection = null; | ||
| 498 | + try { | ||
| 499 | + connection = dataSource.getConnection(); | ||
| 500 | + DatabaseMetaData databaseMetaData = connection.getMetaData(); | ||
| 501 | + String databaseProductName = databaseMetaData.getDatabaseProductName(); | ||
| 502 | + logger.debug("database product name: '{}'", databaseProductName); | ||
| 503 | + | ||
| 504 | + // CRDB does not expose the version through the jdbc driver, so we need to fetch it through version(). | ||
| 505 | + if (PRODUCT_NAME_POSTGRES.equalsIgnoreCase(databaseProductName)) { | ||
| 506 | + try (PreparedStatement preparedStatement = connection.prepareStatement("select version() as version;"); | ||
| 507 | + ResultSet resultSet = preparedStatement.executeQuery()) { | ||
| 508 | + String version = null; | ||
| 509 | + if (resultSet.next()) { | ||
| 510 | + version = resultSet.getString("version"); | ||
| 511 | + } | ||
| 512 | + | ||
| 513 | + if (StringUtils.isNotEmpty(version) && version.toLowerCase().startsWith(PRODUCT_NAME_CRDB.toLowerCase())) { | ||
| 514 | + databaseProductName = PRODUCT_NAME_CRDB; | ||
| 515 | + logger.info("CockroachDB version '{}' detected", version); | ||
| 516 | + } | ||
| 517 | + } | ||
| 518 | + } | ||
| 519 | + | ||
| 520 | + databaseType = databaseTypeMappings.getProperty(databaseProductName); | ||
| 521 | + if (databaseType == null) { | ||
| 522 | + throw new FlowableException("couldn't deduct database type from database product name '" + databaseProductName + "'"); | ||
| 523 | + } | ||
| 524 | + logger.debug("using database type: {}", databaseType); | ||
| 525 | + | ||
| 526 | + } catch (SQLException e) { | ||
| 527 | + throw new RuntimeException("Exception while initializing Database connection", e); | ||
| 528 | + } finally { | ||
| 529 | + try { | ||
| 530 | + if (connection != null) { | ||
| 531 | + connection.close(); | ||
| 532 | + } | ||
| 533 | + } catch (SQLException e) { | ||
| 534 | + logger.error("Exception while closing the Database connection", e); | ||
| 535 | + } | ||
| 536 | + } | ||
| 537 | + | ||
| 538 | + // Special care for MSSQL, as it has a hard limit of 2000 params per statement (incl bulk statement). | ||
| 539 | + // Especially with executions, with 100 as default, this limit is passed. | ||
| 540 | + if (DATABASE_TYPE_MSSQL.equals(databaseType)) { | ||
| 541 | + maxNrOfStatementsInBulkInsert = DEFAULT_MAX_NR_OF_STATEMENTS_BULK_INSERT_SQL_SERVER; | ||
| 542 | + } | ||
| 543 | + } | ||
| 544 | + | ||
| 545 | + public void initSchemaManager() { | ||
| 546 | + if (this.commonSchemaManager == null) { | ||
| 547 | + this.commonSchemaManager = new CommonDbSchemaManager(); | ||
| 548 | + } | ||
| 549 | + } | ||
| 550 | + | ||
| 551 | + // session factories //////////////////////////////////////////////////////// | ||
| 552 | + | ||
| 553 | + public void addSessionFactory(SessionFactory sessionFactory) { | ||
| 554 | + sessionFactories.put(sessionFactory.getSessionType(), sessionFactory); | ||
| 555 | + } | ||
| 556 | + | ||
| 557 | + public void initCommandContextFactory() { | ||
| 558 | + if (commandContextFactory == null) { | ||
| 559 | + commandContextFactory = new CommandContextFactory(); | ||
| 560 | + } | ||
| 561 | + } | ||
| 562 | + | ||
| 563 | + public void initTransactionContextFactory() { | ||
| 564 | + if (transactionContextFactory == null) { | ||
| 565 | + transactionContextFactory = new StandaloneMybatisTransactionContextFactory(); | ||
| 566 | + } | ||
| 567 | + } | ||
| 568 | + | ||
| 569 | + public void initCommandExecutors() { | ||
| 570 | + initDefaultCommandConfig(); | ||
| 571 | + initSchemaCommandConfig(); | ||
| 572 | + initCommandInvoker(); | ||
| 573 | + initCommandInterceptors(); | ||
| 574 | + initCommandExecutor(); | ||
| 575 | + } | ||
| 576 | + | ||
| 577 | + | ||
| 578 | + public void initDefaultCommandConfig() { | ||
| 579 | + if (defaultCommandConfig == null) { | ||
| 580 | + defaultCommandConfig = new CommandConfig(); | ||
| 581 | + } | ||
| 582 | + } | ||
| 583 | + | ||
| 584 | + public void initSchemaCommandConfig() { | ||
| 585 | + if (schemaCommandConfig == null) { | ||
| 586 | + schemaCommandConfig = new CommandConfig(); | ||
| 587 | + } | ||
| 588 | + } | ||
| 589 | + | ||
| 590 | + public void initCommandInvoker() { | ||
| 591 | + if (commandInvoker == null) { | ||
| 592 | + commandInvoker = new DefaultCommandInvoker(); | ||
| 593 | + } | ||
| 594 | + } | ||
| 595 | + | ||
| 596 | + public void initCommandInterceptors() { | ||
| 597 | + if (commandInterceptors == null) { | ||
| 598 | + commandInterceptors = new ArrayList<>(); | ||
| 599 | + if (customPreCommandInterceptors != null) { | ||
| 600 | + commandInterceptors.addAll(customPreCommandInterceptors); | ||
| 601 | + } | ||
| 602 | + commandInterceptors.addAll(getDefaultCommandInterceptors()); | ||
| 603 | + if (customPostCommandInterceptors != null) { | ||
| 604 | + commandInterceptors.addAll(customPostCommandInterceptors); | ||
| 605 | + } | ||
| 606 | + commandInterceptors.add(commandInvoker); | ||
| 607 | + } | ||
| 608 | + } | ||
| 609 | + | ||
| 610 | + public Collection<? extends CommandInterceptor> getDefaultCommandInterceptors() { | ||
| 611 | + if (defaultCommandInterceptors == null) { | ||
| 612 | + List<CommandInterceptor> interceptors = new ArrayList<>(); | ||
| 613 | + interceptors.add(new LogInterceptor()); | ||
| 614 | + | ||
| 615 | + if (DATABASE_TYPE_COCKROACHDB.equals(databaseType)) { | ||
| 616 | + interceptors.add(new CrDbRetryInterceptor()); | ||
| 617 | + } | ||
| 618 | + | ||
| 619 | + CommandInterceptor transactionInterceptor = createTransactionInterceptor(); | ||
| 620 | + if (transactionInterceptor != null) { | ||
| 621 | + interceptors.add(transactionInterceptor); | ||
| 622 | + } | ||
| 623 | + | ||
| 624 | + if (commandContextFactory != null) { | ||
| 625 | + String engineCfgKey = getEngineCfgKey(); | ||
| 626 | + CommandContextInterceptor commandContextInterceptor = new CommandContextInterceptor(commandContextFactory, | ||
| 627 | + classLoader, useClassForNameClassLoading, clock, objectMapper); | ||
| 628 | + engineConfigurations.put(engineCfgKey, this); | ||
| 629 | + commandContextInterceptor.setEngineCfgKey(engineCfgKey); | ||
| 630 | + commandContextInterceptor.setEngineConfigurations(engineConfigurations); | ||
| 631 | + interceptors.add(commandContextInterceptor); | ||
| 632 | + } | ||
| 633 | + | ||
| 634 | + if (transactionContextFactory != null) { | ||
| 635 | + interceptors.add(new TransactionContextInterceptor(transactionContextFactory)); | ||
| 636 | + } | ||
| 637 | + | ||
| 638 | + List<CommandInterceptor> additionalCommandInterceptors = getAdditionalDefaultCommandInterceptors(); | ||
| 639 | + if (additionalCommandInterceptors != null) { | ||
| 640 | + interceptors.addAll(additionalCommandInterceptors); | ||
| 641 | + } | ||
| 642 | + | ||
| 643 | + defaultCommandInterceptors = interceptors; | ||
| 644 | + } | ||
| 645 | + return defaultCommandInterceptors; | ||
| 646 | + } | ||
| 647 | + | ||
| 648 | + public abstract String getEngineCfgKey(); | ||
| 649 | + | ||
| 650 | + public abstract String getEngineScopeType(); | ||
| 651 | + | ||
| 652 | + public List<CommandInterceptor> getAdditionalDefaultCommandInterceptors() { | ||
| 653 | + return null; | ||
| 654 | + } | ||
| 655 | + | ||
| 656 | + public void initCommandExecutor() { | ||
| 657 | + if (commandExecutor == null) { | ||
| 658 | + CommandInterceptor first = initInterceptorChain(commandInterceptors); | ||
| 659 | + commandExecutor = new CommandExecutorImpl(getDefaultCommandConfig(), first); | ||
| 660 | + } | ||
| 661 | + } | ||
| 662 | + | ||
| 663 | + public CommandInterceptor initInterceptorChain(List<CommandInterceptor> chain) { | ||
| 664 | + if (chain == null || chain.isEmpty()) { | ||
| 665 | + throw new FlowableException("invalid command interceptor chain configuration: " + chain); | ||
| 666 | + } | ||
| 667 | + for (int i = 0; i < chain.size() - 1; i++) { | ||
| 668 | + chain.get(i).setNext(chain.get(i + 1)); | ||
| 669 | + } | ||
| 670 | + return chain.get(0); | ||
| 671 | + } | ||
| 672 | + | ||
| 673 | + public abstract CommandInterceptor createTransactionInterceptor(); | ||
| 674 | + | ||
| 675 | + | ||
| 676 | + public void initBeans() { | ||
| 677 | + if (beans == null) { | ||
| 678 | + beans = new HashMap<>(); | ||
| 679 | + } | ||
| 680 | + } | ||
| 681 | + | ||
| 682 | + // id generator | ||
| 683 | + // ///////////////////////////////////////////////////////////// | ||
| 684 | + | ||
| 685 | + public void initIdGenerator() { | ||
| 686 | + if (idGenerator == null) { | ||
| 687 | + idGenerator = new StrongUuidGenerator(); | ||
| 688 | + } | ||
| 689 | + } | ||
| 690 | + | ||
| 691 | + public void initObjectMapper() { | ||
| 692 | + if (objectMapper == null) { | ||
| 693 | + objectMapper = new ObjectMapper(); | ||
| 694 | + objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); | ||
| 695 | + } | ||
| 696 | + } | ||
| 697 | + | ||
| 698 | + public void initClock() { | ||
| 699 | + if (clock == null) { | ||
| 700 | + clock = new DefaultClockImpl(); | ||
| 701 | + } | ||
| 702 | + } | ||
| 703 | + | ||
| 704 | + // Data managers /////////////////////////////////////////////////////////// | ||
| 705 | + | ||
| 706 | + public void initDataManagers() { | ||
| 707 | + if (propertyDataManager == null) { | ||
| 708 | + propertyDataManager = new MybatisPropertyDataManager(idGenerator); | ||
| 709 | + } | ||
| 710 | + | ||
| 711 | + if (byteArrayDataManager == null) { | ||
| 712 | + byteArrayDataManager = new MybatisByteArrayDataManager(idGenerator); | ||
| 713 | + } | ||
| 714 | + } | ||
| 715 | + | ||
| 716 | + // Entity managers ////////////////////////////////////////////////////////// | ||
| 717 | + | ||
| 718 | + public void initEntityManagers() { | ||
| 719 | + if (propertyEntityManager == null) { | ||
| 720 | + propertyEntityManager = new PropertyEntityManagerImpl(this, propertyDataManager); | ||
| 721 | + } | ||
| 722 | + | ||
| 723 | + if (byteArrayEntityManager == null) { | ||
| 724 | + byteArrayEntityManager = new ByteArrayEntityManagerImpl(byteArrayDataManager, getEngineCfgKey(), this::getEventDispatcher); | ||
| 725 | + } | ||
| 726 | + | ||
| 727 | + if (tableDataManager == null) { | ||
| 728 | + tableDataManager = new TableDataManagerImpl(this); | ||
| 729 | + } | ||
| 730 | + } | ||
| 731 | + | ||
| 732 | + // services | ||
| 733 | + // ///////////////////////////////////////////////////////////////// | ||
| 734 | + | ||
| 735 | + protected void initService(Object service) { | ||
| 736 | + if (service instanceof CommonEngineServiceImpl) { | ||
| 737 | + ((CommonEngineServiceImpl) service).setCommandExecutor(commandExecutor); | ||
| 738 | + } | ||
| 739 | + } | ||
| 740 | + | ||
| 741 | + // myBatis SqlSessionFactory | ||
| 742 | + // //////////////////////////////////////////////// | ||
| 743 | + | ||
| 744 | + public void initSessionFactories() { | ||
| 745 | + if (sessionFactories == null) { | ||
| 746 | + sessionFactories = new HashMap<>(); | ||
| 747 | + | ||
| 748 | + if (usingRelationalDatabase) { | ||
| 749 | + initDbSqlSessionFactory(); | ||
| 750 | + } | ||
| 751 | + | ||
| 752 | + addSessionFactory(new GenericManagerFactory(EntityCache.class, EntityCacheImpl.class)); | ||
| 753 | + | ||
| 754 | + if (isLoggingSessionEnabled()) { | ||
| 755 | + if (!sessionFactories.containsKey(LoggingSession.class)) { | ||
| 756 | + LoggingSessionFactory loggingSessionFactory = new LoggingSessionFactory(); | ||
| 757 | + loggingSessionFactory.setLoggingListener(loggingListener); | ||
| 758 | + loggingSessionFactory.setObjectMapper(objectMapper); | ||
| 759 | + sessionFactories.put(LoggingSession.class, loggingSessionFactory); | ||
| 760 | + } | ||
| 761 | + } | ||
| 762 | + | ||
| 763 | + commandContextFactory.setSessionFactories(sessionFactories); | ||
| 764 | + | ||
| 765 | + } else { | ||
| 766 | + if (usingRelationalDatabase) { | ||
| 767 | + initDbSqlSessionFactoryEntitySettings(); | ||
| 768 | + } | ||
| 769 | + } | ||
| 770 | + | ||
| 771 | + if (customSessionFactories != null) { | ||
| 772 | + for (SessionFactory sessionFactory : customSessionFactories) { | ||
| 773 | + addSessionFactory(sessionFactory); | ||
| 774 | + } | ||
| 775 | + } | ||
| 776 | + } | ||
| 777 | + | ||
| 778 | + public void initDbSqlSessionFactory() { | ||
| 779 | + if (dbSqlSessionFactory == null) { | ||
| 780 | + dbSqlSessionFactory = createDbSqlSessionFactory(); | ||
| 781 | + } | ||
| 782 | + dbSqlSessionFactory.setDatabaseType(databaseType); | ||
| 783 | + dbSqlSessionFactory.setSqlSessionFactory(sqlSessionFactory); | ||
| 784 | + dbSqlSessionFactory.setDbHistoryUsed(isDbHistoryUsed); | ||
| 785 | + dbSqlSessionFactory.setDatabaseTablePrefix(databaseTablePrefix); | ||
| 786 | + dbSqlSessionFactory.setTablePrefixIsSchema(tablePrefixIsSchema); | ||
| 787 | + dbSqlSessionFactory.setDatabaseCatalog(databaseCatalog); | ||
| 788 | + dbSqlSessionFactory.setDatabaseSchema(databaseSchema); | ||
| 789 | + dbSqlSessionFactory.setMaxNrOfStatementsInBulkInsert(maxNrOfStatementsInBulkInsert); | ||
| 790 | + | ||
| 791 | + initDbSqlSessionFactoryEntitySettings(); | ||
| 792 | + | ||
| 793 | + addSessionFactory(dbSqlSessionFactory); | ||
| 794 | + } | ||
| 795 | + | ||
| 796 | + public DbSqlSessionFactory createDbSqlSessionFactory() { | ||
| 797 | + return new DbSqlSessionFactory(usePrefixId); | ||
| 798 | + } | ||
| 799 | + | ||
| 800 | + protected abstract void initDbSqlSessionFactoryEntitySettings(); | ||
| 801 | + | ||
| 802 | + protected void defaultInitDbSqlSessionFactoryEntitySettings(List<Class<? extends Entity>> insertOrder, List<Class<? extends Entity>> deleteOrder) { | ||
| 803 | + if (insertOrder != null) { | ||
| 804 | + for (Class<? extends Entity> clazz : insertOrder) { | ||
| 805 | + dbSqlSessionFactory.getInsertionOrder().add(clazz); | ||
| 806 | + | ||
| 807 | + if (isBulkInsertEnabled) { | ||
| 808 | + dbSqlSessionFactory.getBulkInserteableEntityClasses().add(clazz); | ||
| 809 | + } | ||
| 810 | + } | ||
| 811 | + } | ||
| 812 | + | ||
| 813 | + if (deleteOrder != null) { | ||
| 814 | + for (Class<? extends Entity> clazz : deleteOrder) { | ||
| 815 | + dbSqlSessionFactory.getDeletionOrder().add(clazz); | ||
| 816 | + } | ||
| 817 | + } | ||
| 818 | + } | ||
| 819 | + | ||
| 820 | + public void initTransactionFactory() { | ||
| 821 | + if (transactionFactory == null) { | ||
| 822 | + if (transactionsExternallyManaged) { | ||
| 823 | + transactionFactory = new ManagedTransactionFactory(); | ||
| 824 | + Properties properties = new Properties(); | ||
| 825 | + properties.put("closeConnection", "false"); | ||
| 826 | + this.transactionFactory.setProperties(properties); | ||
| 827 | + } else { | ||
| 828 | + transactionFactory = new JdbcTransactionFactory(); | ||
| 829 | + } | ||
| 830 | + } | ||
| 831 | + } | ||
| 832 | + | ||
| 833 | + public void initSqlSessionFactory() { | ||
| 834 | + if (sqlSessionFactory == null) { | ||
| 835 | + InputStream inputStream = null; | ||
| 836 | + try { | ||
| 837 | + inputStream = getMyBatisXmlConfigurationStream(); | ||
| 838 | + | ||
| 839 | + Environment environment = new Environment("default", transactionFactory, dataSource); | ||
| 840 | + Reader reader = new InputStreamReader(inputStream); | ||
| 841 | + Properties properties = new Properties(); | ||
| 842 | + properties.put("prefix", databaseTablePrefix); | ||
| 843 | + | ||
| 844 | + String wildcardEscapeClause = ""; | ||
| 845 | + if ((databaseWildcardEscapeCharacter != null) && (databaseWildcardEscapeCharacter.length() != 0)) { | ||
| 846 | + wildcardEscapeClause = " escape '" + databaseWildcardEscapeCharacter + "'"; | ||
| 847 | + } | ||
| 848 | + properties.put("wildcardEscapeClause", wildcardEscapeClause); | ||
| 849 | + | ||
| 850 | + // set default properties | ||
| 851 | + properties.put("limitBefore", ""); | ||
| 852 | + properties.put("limitAfter", ""); | ||
| 853 | + properties.put("limitBetween", ""); | ||
| 854 | + properties.put("limitBeforeNativeQuery", ""); | ||
| 855 | + properties.put("limitAfterNativeQuery", ""); | ||
| 856 | + properties.put("blobType", "BLOB"); | ||
| 857 | + properties.put("boolValue", "TRUE"); | ||
| 858 | + | ||
| 859 | + if (databaseType != null) { | ||
| 860 | + properties.load(getResourceAsStream(pathToEngineDbProperties())); | ||
| 861 | + } | ||
| 862 | + | ||
| 863 | + Configuration configuration = initMybatisConfiguration(environment, reader, properties); | ||
| 864 | + sqlSessionFactory = new DefaultSqlSessionFactory(configuration); | ||
| 865 | + | ||
| 866 | + } catch (Exception e) { | ||
| 867 | + throw new FlowableException("Error while building ibatis SqlSessionFactory: " + e.getMessage(), e); | ||
| 868 | + } finally { | ||
| 869 | + IoUtil.closeSilently(inputStream); | ||
| 870 | + } | ||
| 871 | + } else { | ||
| 872 | + // This is needed when the SQL Session Factory is created by another engine. | ||
| 873 | + // When custom XML Mappers are registered with this engine they need to be loaded in the configuration as well | ||
| 874 | + applyCustomMybatisCustomizations(sqlSessionFactory.getConfiguration()); | ||
| 875 | + } | ||
| 876 | + } | ||
| 877 | + | ||
| 878 | + public String pathToEngineDbProperties() { | ||
| 879 | + return "org/flowable/common/db/properties/" + databaseType + ".properties"; | ||
| 880 | + } | ||
| 881 | + | ||
| 882 | + public Configuration initMybatisConfiguration(Environment environment, Reader reader, Properties properties) { | ||
| 883 | + XMLConfigBuilder parser = new XMLConfigBuilder(reader, "", properties); | ||
| 884 | + Configuration configuration = parser.getConfiguration(); | ||
| 885 | + | ||
| 886 | + if (databaseType != null) { | ||
| 887 | + configuration.setDatabaseId(databaseType); | ||
| 888 | + } | ||
| 889 | + | ||
| 890 | + configuration.setEnvironment(environment); | ||
| 891 | + | ||
| 892 | + initMybatisTypeHandlers(configuration); | ||
| 893 | + initCustomMybatisInterceptors(configuration); | ||
| 894 | + if (isEnableLogSqlExecutionTime()) { | ||
| 895 | + initMyBatisLogSqlExecutionTimePlugin(configuration); | ||
| 896 | + } | ||
| 897 | + | ||
| 898 | + configuration = parseMybatisConfiguration(parser); | ||
| 899 | + return configuration; | ||
| 900 | + } | ||
| 901 | + | ||
| 902 | + public void initCustomMybatisMappers(Configuration configuration) { | ||
| 903 | + if (getCustomMybatisMappers() != null) { | ||
| 904 | + for (Class<?> clazz : getCustomMybatisMappers()) { | ||
| 905 | + if (!configuration.hasMapper(clazz)) { | ||
| 906 | + configuration.addMapper(clazz); | ||
| 907 | + } | ||
| 908 | + } | ||
| 909 | + } | ||
| 910 | + } | ||
| 911 | + | ||
| 912 | + public void initMybatisTypeHandlers(Configuration configuration) { | ||
| 913 | + // When mapping into Map<String, Object> there is currently a problem with MyBatis. | ||
| 914 | + // It will return objects which are driver specific. | ||
| 915 | + // Therefore we are registering the mappings between Object.class and the specific jdbc type here. | ||
| 916 | + // see https://github.com/mybatis/mybatis-3/issues/2216 for more info | ||
| 917 | + TypeHandlerRegistry handlerRegistry = configuration.getTypeHandlerRegistry(); | ||
| 918 | + | ||
| 919 | + handlerRegistry.register(Object.class, JdbcType.BOOLEAN, new BooleanTypeHandler()); | ||
| 920 | + handlerRegistry.register(Object.class, JdbcType.BIT, new BooleanTypeHandler()); | ||
| 921 | + | ||
| 922 | + handlerRegistry.register(Object.class, JdbcType.TINYINT, new ByteTypeHandler()); | ||
| 923 | + | ||
| 924 | + handlerRegistry.register(Object.class, JdbcType.SMALLINT, new ShortTypeHandler()); | ||
| 925 | + | ||
| 926 | + handlerRegistry.register(Object.class, JdbcType.INTEGER, new IntegerTypeHandler()); | ||
| 927 | + | ||
| 928 | + handlerRegistry.register(Object.class, JdbcType.FLOAT, new FloatTypeHandler()); | ||
| 929 | + | ||
| 930 | + handlerRegistry.register(Object.class, JdbcType.DOUBLE, new DoubleTypeHandler()); | ||
| 931 | + | ||
| 932 | + handlerRegistry.register(Object.class, JdbcType.CHAR, new StringTypeHandler()); | ||
| 933 | + handlerRegistry.register(Object.class, JdbcType.CLOB, new ClobTypeHandler()); | ||
| 934 | + handlerRegistry.register(Object.class, JdbcType.VARCHAR, new StringTypeHandler()); | ||
| 935 | + handlerRegistry.register(Object.class, JdbcType.LONGVARCHAR, new StringTypeHandler()); | ||
| 936 | + handlerRegistry.register(Object.class, JdbcType.NVARCHAR, new NStringTypeHandler()); | ||
| 937 | + handlerRegistry.register(Object.class, JdbcType.NCHAR, new NStringTypeHandler()); | ||
| 938 | + handlerRegistry.register(Object.class, JdbcType.NCLOB, new NClobTypeHandler()); | ||
| 939 | + | ||
| 940 | + handlerRegistry.register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler()); | ||
| 941 | + | ||
| 942 | + handlerRegistry.register(Object.class, JdbcType.BIGINT, new LongTypeHandler()); | ||
| 943 | + | ||
| 944 | + handlerRegistry.register(Object.class, JdbcType.REAL, new BigDecimalTypeHandler()); | ||
| 945 | + handlerRegistry.register(Object.class, JdbcType.DECIMAL, new BigDecimalTypeHandler()); | ||
| 946 | + handlerRegistry.register(Object.class, JdbcType.NUMERIC, new BigDecimalTypeHandler()); | ||
| 947 | + | ||
| 948 | + handlerRegistry.register(Object.class, JdbcType.BLOB, new BlobInputStreamTypeHandler()); | ||
| 949 | + handlerRegistry.register(Object.class, JdbcType.LONGVARBINARY, new BlobTypeHandler()); | ||
| 950 | + | ||
| 951 | + handlerRegistry.register(Object.class, JdbcType.DATE, new DateOnlyTypeHandler()); | ||
| 952 | + handlerRegistry.register(Object.class, JdbcType.TIME, new TimeOnlyTypeHandler()); | ||
| 953 | + handlerRegistry.register(Object.class, JdbcType.TIMESTAMP, new DateTypeHandler()); | ||
| 954 | + | ||
| 955 | + handlerRegistry.register(Object.class, JdbcType.SQLXML, new SqlxmlTypeHandler()); | ||
| 956 | + } | ||
| 957 | + | ||
| 958 | + public void initCustomMybatisInterceptors(Configuration configuration) { | ||
| 959 | + if (customMybatisInterceptors!=null){ | ||
| 960 | + for (Interceptor interceptor :customMybatisInterceptors){ | ||
| 961 | + configuration.addInterceptor(interceptor); | ||
| 962 | + } | ||
| 963 | + } | ||
| 964 | + } | ||
| 965 | + | ||
| 966 | + public void initMyBatisLogSqlExecutionTimePlugin(Configuration configuration) { | ||
| 967 | + configuration.addInterceptor(new LogSqlExecutionTimePlugin()); | ||
| 968 | + } | ||
| 969 | + | ||
| 970 | + public Configuration parseMybatisConfiguration(XMLConfigBuilder parser) { | ||
| 971 | + Configuration configuration = parser.parse(); | ||
| 972 | + | ||
| 973 | + applyCustomMybatisCustomizations(configuration); | ||
| 974 | + return configuration; | ||
| 975 | + } | ||
| 976 | + | ||
| 977 | + protected void applyCustomMybatisCustomizations(Configuration configuration) { | ||
| 978 | + initCustomMybatisMappers(configuration); | ||
| 979 | + | ||
| 980 | + if (dependentEngineMybatisTypeAliasConfigs != null) { | ||
| 981 | + for (MybatisTypeAliasConfigurator typeAliasConfig : dependentEngineMybatisTypeAliasConfigs) { | ||
| 982 | + typeAliasConfig.configure(configuration.getTypeAliasRegistry()); | ||
| 983 | + } | ||
| 984 | + } | ||
| 985 | + if (dependentEngineMybatisTypeHandlerConfigs != null) { | ||
| 986 | + for (MybatisTypeHandlerConfigurator typeHandlerConfig : dependentEngineMybatisTypeHandlerConfigs) { | ||
| 987 | + typeHandlerConfig.configure(configuration.getTypeHandlerRegistry()); | ||
| 988 | + } | ||
| 989 | + } | ||
| 990 | + | ||
| 991 | + parseDependentEngineMybatisXMLMappers(configuration); | ||
| 992 | + parseCustomMybatisXMLMappers(configuration); | ||
| 993 | + } | ||
| 994 | + | ||
| 995 | + public void parseCustomMybatisXMLMappers(Configuration configuration) { | ||
| 996 | + if (getCustomMybatisXMLMappers() != null) { | ||
| 997 | + for (String resource : getCustomMybatisXMLMappers()) { | ||
| 998 | + parseMybatisXmlMapping(configuration, resource); | ||
| 999 | + } | ||
| 1000 | + } | ||
| 1001 | + } | ||
| 1002 | + | ||
| 1003 | + public void parseDependentEngineMybatisXMLMappers(Configuration configuration) { | ||
| 1004 | + if (getDependentEngineMyBatisXmlMappers() != null) { | ||
| 1005 | + for (String resource : getDependentEngineMyBatisXmlMappers()) { | ||
| 1006 | + parseMybatisXmlMapping(configuration, resource); | ||
| 1007 | + } | ||
| 1008 | + } | ||
| 1009 | + } | ||
| 1010 | + | ||
| 1011 | + protected void parseMybatisXmlMapping(Configuration configuration, String resource) { | ||
| 1012 | + // see XMLConfigBuilder.mapperElement() | ||
| 1013 | + XMLMapperBuilder mapperParser = new XMLMapperBuilder(getResourceAsStream(resource), configuration, resource, configuration.getSqlFragments()); | ||
| 1014 | + mapperParser.parse(); | ||
| 1015 | + } | ||
| 1016 | + | ||
| 1017 | + protected InputStream getResourceAsStream(String resource) { | ||
| 1018 | + ClassLoader classLoader = getClassLoader(); | ||
| 1019 | + if (classLoader != null) { | ||
| 1020 | + return getClassLoader().getResourceAsStream(resource); | ||
| 1021 | + } else { | ||
| 1022 | + return this.getClass().getClassLoader().getResourceAsStream(resource); | ||
| 1023 | + } | ||
| 1024 | + } | ||
| 1025 | + | ||
| 1026 | + public void setMybatisMappingFile(String file) { | ||
| 1027 | + this.mybatisMappingFile = file; | ||
| 1028 | + } | ||
| 1029 | + | ||
| 1030 | + public String getMybatisMappingFile() { | ||
| 1031 | + return mybatisMappingFile; | ||
| 1032 | + } | ||
| 1033 | + | ||
| 1034 | + public abstract InputStream getMyBatisXmlConfigurationStream(); | ||
| 1035 | + | ||
| 1036 | + public void initConfigurators() { | ||
| 1037 | + | ||
| 1038 | + allConfigurators = new ArrayList<>(); | ||
| 1039 | + allConfigurators.addAll(getEngineSpecificEngineConfigurators()); | ||
| 1040 | + | ||
| 1041 | + // Configurators that are explicitly added to the config | ||
| 1042 | + if (configurators != null) { | ||
| 1043 | + allConfigurators.addAll(configurators); | ||
| 1044 | + } | ||
| 1045 | + | ||
| 1046 | + // Auto discovery through ServiceLoader | ||
| 1047 | + if (enableConfiguratorServiceLoader) { | ||
| 1048 | + ClassLoader classLoader = getClassLoader(); | ||
| 1049 | + if (classLoader == null) { | ||
| 1050 | + classLoader = ReflectUtil.getClassLoader(); | ||
| 1051 | + } | ||
| 1052 | + | ||
| 1053 | + ServiceLoader<EngineConfigurator> configuratorServiceLoader = ServiceLoader.load(EngineConfigurator.class, classLoader); | ||
| 1054 | + int nrOfServiceLoadedConfigurators = 0; | ||
| 1055 | + for (EngineConfigurator configurator : configuratorServiceLoader) { | ||
| 1056 | + allConfigurators.add(configurator); | ||
| 1057 | + nrOfServiceLoadedConfigurators++; | ||
| 1058 | + } | ||
| 1059 | + | ||
| 1060 | + if (nrOfServiceLoadedConfigurators > 0) { | ||
| 1061 | + logger.info("Found {} auto-discoverable Process Engine Configurator{}", nrOfServiceLoadedConfigurators, nrOfServiceLoadedConfigurators > 1 ? "s" : ""); | ||
| 1062 | + } | ||
| 1063 | + | ||
| 1064 | + if (!allConfigurators.isEmpty()) { | ||
| 1065 | + | ||
| 1066 | + // Order them according to the priorities (useful for dependent | ||
| 1067 | + // configurator) | ||
| 1068 | + allConfigurators.sort(new Comparator<EngineConfigurator>() { | ||
| 1069 | + | ||
| 1070 | + @Override | ||
| 1071 | + public int compare(EngineConfigurator configurator1, EngineConfigurator configurator2) { | ||
| 1072 | + int priority1 = configurator1.getPriority(); | ||
| 1073 | + int priority2 = configurator2.getPriority(); | ||
| 1074 | + | ||
| 1075 | + if (priority1 < priority2) { | ||
| 1076 | + return -1; | ||
| 1077 | + } else if (priority1 > priority2) { | ||
| 1078 | + return 1; | ||
| 1079 | + } | ||
| 1080 | + return 0; | ||
| 1081 | + } | ||
| 1082 | + }); | ||
| 1083 | + | ||
| 1084 | + // Execute the configurators | ||
| 1085 | + logger.info("Found {} Engine Configurators in total:", allConfigurators.size()); | ||
| 1086 | + for (EngineConfigurator configurator : allConfigurators) { | ||
| 1087 | + logger.info("{} (priority:{})", configurator.getClass(), configurator.getPriority()); | ||
| 1088 | + } | ||
| 1089 | + | ||
| 1090 | + } | ||
| 1091 | + | ||
| 1092 | + } | ||
| 1093 | + } | ||
| 1094 | + | ||
| 1095 | + public void close() { | ||
| 1096 | + if (forceCloseMybatisConnectionPool && dataSource instanceof PooledDataSource) { | ||
| 1097 | + /* | ||
| 1098 | + * When the datasource is created by a Flowable engine (i.e. it's an instance of PooledDataSource), | ||
| 1099 | + * the connection pool needs to be closed when closing the engine. | ||
| 1100 | + * Note that calling forceCloseAll() multiple times (as is the case when running with multiple engine) is ok. | ||
| 1101 | + */ | ||
| 1102 | + ((PooledDataSource) dataSource).forceCloseAll(); | ||
| 1103 | + } | ||
| 1104 | + } | ||
| 1105 | + | ||
| 1106 | + protected List<EngineConfigurator> getEngineSpecificEngineConfigurators() { | ||
| 1107 | + // meant to be overridden if needed | ||
| 1108 | + return Collections.emptyList(); | ||
| 1109 | + } | ||
| 1110 | + | ||
| 1111 | + public void configuratorsBeforeInit() { | ||
| 1112 | + for (EngineConfigurator configurator : allConfigurators) { | ||
| 1113 | + logger.info("Executing beforeInit() of {} (priority:{})", configurator.getClass(), configurator.getPriority()); | ||
| 1114 | + configurator.beforeInit(this); | ||
| 1115 | + } | ||
| 1116 | + } | ||
| 1117 | + | ||
| 1118 | + public void configuratorsAfterInit() { | ||
| 1119 | + for (EngineConfigurator configurator : allConfigurators) { | ||
| 1120 | + logger.info("Executing configure() of {} (priority:{})", configurator.getClass(), configurator.getPriority()); | ||
| 1121 | + configurator.configure(this); | ||
| 1122 | + } | ||
| 1123 | + } | ||
| 1124 | + | ||
| 1125 | + public LockManager getLockManager(String lockName) { | ||
| 1126 | + return new LockManagerImpl(commandExecutor, lockName, getLockPollRate(), getEngineCfgKey()); | ||
| 1127 | + } | ||
| 1128 | + | ||
| 1129 | + // getters and setters | ||
| 1130 | + // ////////////////////////////////////////////////////// | ||
| 1131 | + | ||
| 1132 | + public abstract String getEngineName(); | ||
| 1133 | + | ||
| 1134 | + public ClassLoader getClassLoader() { | ||
| 1135 | + return classLoader; | ||
| 1136 | + } | ||
| 1137 | + | ||
| 1138 | + public AbstractEngineConfiguration setClassLoader(ClassLoader classLoader) { | ||
| 1139 | + this.classLoader = classLoader; | ||
| 1140 | + return this; | ||
| 1141 | + } | ||
| 1142 | + | ||
| 1143 | + public boolean isUseClassForNameClassLoading() { | ||
| 1144 | + return useClassForNameClassLoading; | ||
| 1145 | + } | ||
| 1146 | + | ||
| 1147 | + public AbstractEngineConfiguration setUseClassForNameClassLoading(boolean useClassForNameClassLoading) { | ||
| 1148 | + this.useClassForNameClassLoading = useClassForNameClassLoading; | ||
| 1149 | + return this; | ||
| 1150 | + } | ||
| 1151 | + | ||
| 1152 | + public void addEngineLifecycleListener(EngineLifecycleListener engineLifecycleListener) { | ||
| 1153 | + if (this.engineLifecycleListeners == null) { | ||
| 1154 | + this.engineLifecycleListeners = new ArrayList<>(); | ||
| 1155 | + } | ||
| 1156 | + this.engineLifecycleListeners.add(engineLifecycleListener); | ||
| 1157 | + } | ||
| 1158 | + | ||
| 1159 | + public List<EngineLifecycleListener> getEngineLifecycleListeners() { | ||
| 1160 | + return engineLifecycleListeners; | ||
| 1161 | + } | ||
| 1162 | + | ||
| 1163 | + public AbstractEngineConfiguration setEngineLifecycleListeners(List<EngineLifecycleListener> engineLifecycleListeners) { | ||
| 1164 | + this.engineLifecycleListeners = engineLifecycleListeners; | ||
| 1165 | + return this; | ||
| 1166 | + } | ||
| 1167 | + | ||
| 1168 | + public String getDatabaseType() { | ||
| 1169 | + return databaseType; | ||
| 1170 | + } | ||
| 1171 | + | ||
| 1172 | + public AbstractEngineConfiguration setDatabaseType(String databaseType) { | ||
| 1173 | + this.databaseType = databaseType; | ||
| 1174 | + return this; | ||
| 1175 | + } | ||
| 1176 | + | ||
| 1177 | + public DataSource getDataSource() { | ||
| 1178 | + return dataSource; | ||
| 1179 | + } | ||
| 1180 | + | ||
| 1181 | + public AbstractEngineConfiguration setDataSource(DataSource dataSource) { | ||
| 1182 | + this.dataSource = dataSource; | ||
| 1183 | + return this; | ||
| 1184 | + } | ||
| 1185 | + | ||
| 1186 | + public SchemaManager getSchemaManager() { | ||
| 1187 | + return schemaManager; | ||
| 1188 | + } | ||
| 1189 | + | ||
| 1190 | + public AbstractEngineConfiguration setSchemaManager(SchemaManager schemaManager) { | ||
| 1191 | + this.schemaManager = schemaManager; | ||
| 1192 | + return this; | ||
| 1193 | + } | ||
| 1194 | + | ||
| 1195 | + public SchemaManager getCommonSchemaManager() { | ||
| 1196 | + return commonSchemaManager; | ||
| 1197 | + } | ||
| 1198 | + | ||
| 1199 | + public AbstractEngineConfiguration setCommonSchemaManager(SchemaManager commonSchemaManager) { | ||
| 1200 | + this.commonSchemaManager = commonSchemaManager; | ||
| 1201 | + return this; | ||
| 1202 | + } | ||
| 1203 | + | ||
| 1204 | + public Command<Void> getSchemaManagementCmd() { | ||
| 1205 | + return schemaManagementCmd; | ||
| 1206 | + } | ||
| 1207 | + | ||
| 1208 | + public AbstractEngineConfiguration setSchemaManagementCmd(Command<Void> schemaManagementCmd) { | ||
| 1209 | + this.schemaManagementCmd = schemaManagementCmd; | ||
| 1210 | + return this; | ||
| 1211 | + } | ||
| 1212 | + | ||
| 1213 | + public String getJdbcDriver() { | ||
| 1214 | + return jdbcDriver; | ||
| 1215 | + } | ||
| 1216 | + | ||
| 1217 | + public AbstractEngineConfiguration setJdbcDriver(String jdbcDriver) { | ||
| 1218 | + this.jdbcDriver = jdbcDriver; | ||
| 1219 | + return this; | ||
| 1220 | + } | ||
| 1221 | + | ||
| 1222 | + public String getJdbcUrl() { | ||
| 1223 | + return jdbcUrl; | ||
| 1224 | + } | ||
| 1225 | + | ||
| 1226 | + public AbstractEngineConfiguration setJdbcUrl(String jdbcUrl) { | ||
| 1227 | + this.jdbcUrl = jdbcUrl; | ||
| 1228 | + return this; | ||
| 1229 | + } | ||
| 1230 | + | ||
| 1231 | + public String getJdbcUsername() { | ||
| 1232 | + return jdbcUsername; | ||
| 1233 | + } | ||
| 1234 | + | ||
| 1235 | + public AbstractEngineConfiguration setJdbcUsername(String jdbcUsername) { | ||
| 1236 | + this.jdbcUsername = jdbcUsername; | ||
| 1237 | + return this; | ||
| 1238 | + } | ||
| 1239 | + | ||
| 1240 | + public String getJdbcPassword() { | ||
| 1241 | + return jdbcPassword; | ||
| 1242 | + } | ||
| 1243 | + | ||
| 1244 | + public AbstractEngineConfiguration setJdbcPassword(String jdbcPassword) { | ||
| 1245 | + this.jdbcPassword = jdbcPassword; | ||
| 1246 | + return this; | ||
| 1247 | + } | ||
| 1248 | + | ||
| 1249 | + public int getJdbcMaxActiveConnections() { | ||
| 1250 | + return jdbcMaxActiveConnections; | ||
| 1251 | + } | ||
| 1252 | + | ||
| 1253 | + public AbstractEngineConfiguration setJdbcMaxActiveConnections(int jdbcMaxActiveConnections) { | ||
| 1254 | + this.jdbcMaxActiveConnections = jdbcMaxActiveConnections; | ||
| 1255 | + return this; | ||
| 1256 | + } | ||
| 1257 | + | ||
| 1258 | + public int getJdbcMaxIdleConnections() { | ||
| 1259 | + return jdbcMaxIdleConnections; | ||
| 1260 | + } | ||
| 1261 | + | ||
| 1262 | + public AbstractEngineConfiguration setJdbcMaxIdleConnections(int jdbcMaxIdleConnections) { | ||
| 1263 | + this.jdbcMaxIdleConnections = jdbcMaxIdleConnections; | ||
| 1264 | + return this; | ||
| 1265 | + } | ||
| 1266 | + | ||
| 1267 | + public int getJdbcMaxCheckoutTime() { | ||
| 1268 | + return jdbcMaxCheckoutTime; | ||
| 1269 | + } | ||
| 1270 | + | ||
| 1271 | + public AbstractEngineConfiguration setJdbcMaxCheckoutTime(int jdbcMaxCheckoutTime) { | ||
| 1272 | + this.jdbcMaxCheckoutTime = jdbcMaxCheckoutTime; | ||
| 1273 | + return this; | ||
| 1274 | + } | ||
| 1275 | + | ||
| 1276 | + public int getJdbcMaxWaitTime() { | ||
| 1277 | + return jdbcMaxWaitTime; | ||
| 1278 | + } | ||
| 1279 | + | ||
| 1280 | + public AbstractEngineConfiguration setJdbcMaxWaitTime(int jdbcMaxWaitTime) { | ||
| 1281 | + this.jdbcMaxWaitTime = jdbcMaxWaitTime; | ||
| 1282 | + return this; | ||
| 1283 | + } | ||
| 1284 | + | ||
| 1285 | + public boolean isJdbcPingEnabled() { | ||
| 1286 | + return jdbcPingEnabled; | ||
| 1287 | + } | ||
| 1288 | + | ||
| 1289 | + public AbstractEngineConfiguration setJdbcPingEnabled(boolean jdbcPingEnabled) { | ||
| 1290 | + this.jdbcPingEnabled = jdbcPingEnabled; | ||
| 1291 | + return this; | ||
| 1292 | + } | ||
| 1293 | + | ||
| 1294 | + public int getJdbcPingConnectionNotUsedFor() { | ||
| 1295 | + return jdbcPingConnectionNotUsedFor; | ||
| 1296 | + } | ||
| 1297 | + | ||
| 1298 | + public AbstractEngineConfiguration setJdbcPingConnectionNotUsedFor(int jdbcPingConnectionNotUsedFor) { | ||
| 1299 | + this.jdbcPingConnectionNotUsedFor = jdbcPingConnectionNotUsedFor; | ||
| 1300 | + return this; | ||
| 1301 | + } | ||
| 1302 | + | ||
| 1303 | + public int getJdbcDefaultTransactionIsolationLevel() { | ||
| 1304 | + return jdbcDefaultTransactionIsolationLevel; | ||
| 1305 | + } | ||
| 1306 | + | ||
| 1307 | + public AbstractEngineConfiguration setJdbcDefaultTransactionIsolationLevel(int jdbcDefaultTransactionIsolationLevel) { | ||
| 1308 | + this.jdbcDefaultTransactionIsolationLevel = jdbcDefaultTransactionIsolationLevel; | ||
| 1309 | + return this; | ||
| 1310 | + } | ||
| 1311 | + | ||
| 1312 | + public String getJdbcPingQuery() { | ||
| 1313 | + return jdbcPingQuery; | ||
| 1314 | + } | ||
| 1315 | + | ||
| 1316 | + public AbstractEngineConfiguration setJdbcPingQuery(String jdbcPingQuery) { | ||
| 1317 | + this.jdbcPingQuery = jdbcPingQuery; | ||
| 1318 | + return this; | ||
| 1319 | + } | ||
| 1320 | + | ||
| 1321 | + public String getDataSourceJndiName() { | ||
| 1322 | + return dataSourceJndiName; | ||
| 1323 | + } | ||
| 1324 | + | ||
| 1325 | + public AbstractEngineConfiguration setDataSourceJndiName(String dataSourceJndiName) { | ||
| 1326 | + this.dataSourceJndiName = dataSourceJndiName; | ||
| 1327 | + return this; | ||
| 1328 | + } | ||
| 1329 | + | ||
| 1330 | + public CommandConfig getSchemaCommandConfig() { | ||
| 1331 | + return schemaCommandConfig; | ||
| 1332 | + } | ||
| 1333 | + | ||
| 1334 | + public AbstractEngineConfiguration setSchemaCommandConfig(CommandConfig schemaCommandConfig) { | ||
| 1335 | + this.schemaCommandConfig = schemaCommandConfig; | ||
| 1336 | + return this; | ||
| 1337 | + } | ||
| 1338 | + | ||
| 1339 | + public boolean isTransactionsExternallyManaged() { | ||
| 1340 | + return transactionsExternallyManaged; | ||
| 1341 | + } | ||
| 1342 | + | ||
| 1343 | + public AbstractEngineConfiguration setTransactionsExternallyManaged(boolean transactionsExternallyManaged) { | ||
| 1344 | + this.transactionsExternallyManaged = transactionsExternallyManaged; | ||
| 1345 | + return this; | ||
| 1346 | + } | ||
| 1347 | + | ||
| 1348 | + public Map<Object, Object> getBeans() { | ||
| 1349 | + return beans; | ||
| 1350 | + } | ||
| 1351 | + | ||
| 1352 | + public AbstractEngineConfiguration setBeans(Map<Object, Object> beans) { | ||
| 1353 | + this.beans = beans; | ||
| 1354 | + return this; | ||
| 1355 | + } | ||
| 1356 | + | ||
| 1357 | + public IdGenerator getIdGenerator() { | ||
| 1358 | + return idGenerator; | ||
| 1359 | + } | ||
| 1360 | + | ||
| 1361 | + public AbstractEngineConfiguration setIdGenerator(IdGenerator idGenerator) { | ||
| 1362 | + this.idGenerator = idGenerator; | ||
| 1363 | + return this; | ||
| 1364 | + } | ||
| 1365 | + | ||
| 1366 | + public boolean isUsePrefixId() { | ||
| 1367 | + return usePrefixId; | ||
| 1368 | + } | ||
| 1369 | + | ||
| 1370 | + public AbstractEngineConfiguration setUsePrefixId(boolean usePrefixId) { | ||
| 1371 | + this.usePrefixId = usePrefixId; | ||
| 1372 | + return this; | ||
| 1373 | + } | ||
| 1374 | + | ||
| 1375 | + public String getXmlEncoding() { | ||
| 1376 | + return xmlEncoding; | ||
| 1377 | + } | ||
| 1378 | + | ||
| 1379 | + public AbstractEngineConfiguration setXmlEncoding(String xmlEncoding) { | ||
| 1380 | + this.xmlEncoding = xmlEncoding; | ||
| 1381 | + return this; | ||
| 1382 | + } | ||
| 1383 | + | ||
| 1384 | + public CommandConfig getDefaultCommandConfig() { | ||
| 1385 | + return defaultCommandConfig; | ||
| 1386 | + } | ||
| 1387 | + | ||
| 1388 | + public AbstractEngineConfiguration setDefaultCommandConfig(CommandConfig defaultCommandConfig) { | ||
| 1389 | + this.defaultCommandConfig = defaultCommandConfig; | ||
| 1390 | + return this; | ||
| 1391 | + } | ||
| 1392 | + | ||
| 1393 | + public CommandExecutor getCommandExecutor() { | ||
| 1394 | + return commandExecutor; | ||
| 1395 | + } | ||
| 1396 | + | ||
| 1397 | + public AbstractEngineConfiguration setCommandExecutor(CommandExecutor commandExecutor) { | ||
| 1398 | + this.commandExecutor = commandExecutor; | ||
| 1399 | + return this; | ||
| 1400 | + } | ||
| 1401 | + | ||
| 1402 | + public CommandContextFactory getCommandContextFactory() { | ||
| 1403 | + return commandContextFactory; | ||
| 1404 | + } | ||
| 1405 | + | ||
| 1406 | + public AbstractEngineConfiguration setCommandContextFactory(CommandContextFactory commandContextFactory) { | ||
| 1407 | + this.commandContextFactory = commandContextFactory; | ||
| 1408 | + return this; | ||
| 1409 | + } | ||
| 1410 | + | ||
| 1411 | + public CommandInterceptor getCommandInvoker() { | ||
| 1412 | + return commandInvoker; | ||
| 1413 | + } | ||
| 1414 | + | ||
| 1415 | + public AbstractEngineConfiguration setCommandInvoker(CommandInterceptor commandInvoker) { | ||
| 1416 | + this.commandInvoker = commandInvoker; | ||
| 1417 | + return this; | ||
| 1418 | + } | ||
| 1419 | + | ||
| 1420 | + public AgendaOperationRunner getAgendaOperationRunner() { | ||
| 1421 | + return agendaOperationRunner; | ||
| 1422 | + } | ||
| 1423 | + | ||
| 1424 | + public AbstractEngineConfiguration setAgendaOperationRunner(AgendaOperationRunner agendaOperationRunner) { | ||
| 1425 | + this.agendaOperationRunner = agendaOperationRunner; | ||
| 1426 | + return this; | ||
| 1427 | + } | ||
| 1428 | + | ||
| 1429 | + public List<CommandInterceptor> getCustomPreCommandInterceptors() { | ||
| 1430 | + return customPreCommandInterceptors; | ||
| 1431 | + } | ||
| 1432 | + | ||
| 1433 | + public AbstractEngineConfiguration setCustomPreCommandInterceptors(List<CommandInterceptor> customPreCommandInterceptors) { | ||
| 1434 | + this.customPreCommandInterceptors = customPreCommandInterceptors; | ||
| 1435 | + return this; | ||
| 1436 | + } | ||
| 1437 | + | ||
| 1438 | + public List<CommandInterceptor> getCustomPostCommandInterceptors() { | ||
| 1439 | + return customPostCommandInterceptors; | ||
| 1440 | + } | ||
| 1441 | + | ||
| 1442 | + public AbstractEngineConfiguration setCustomPostCommandInterceptors(List<CommandInterceptor> customPostCommandInterceptors) { | ||
| 1443 | + this.customPostCommandInterceptors = customPostCommandInterceptors; | ||
| 1444 | + return this; | ||
| 1445 | + } | ||
| 1446 | + | ||
| 1447 | + public List<CommandInterceptor> getCommandInterceptors() { | ||
| 1448 | + return commandInterceptors; | ||
| 1449 | + } | ||
| 1450 | + | ||
| 1451 | + public AbstractEngineConfiguration setCommandInterceptors(List<CommandInterceptor> commandInterceptors) { | ||
| 1452 | + this.commandInterceptors = commandInterceptors; | ||
| 1453 | + return this; | ||
| 1454 | + } | ||
| 1455 | + | ||
| 1456 | + public Map<String, AbstractEngineConfiguration> getEngineConfigurations() { | ||
| 1457 | + return engineConfigurations; | ||
| 1458 | + } | ||
| 1459 | + | ||
| 1460 | + public AbstractEngineConfiguration setEngineConfigurations(Map<String, AbstractEngineConfiguration> engineConfigurations) { | ||
| 1461 | + this.engineConfigurations = engineConfigurations; | ||
| 1462 | + return this; | ||
| 1463 | + } | ||
| 1464 | + | ||
| 1465 | + public void addEngineConfiguration(String key, String scopeType, AbstractEngineConfiguration engineConfiguration) { | ||
| 1466 | + if (engineConfigurations == null) { | ||
| 1467 | + engineConfigurations = new HashMap<>(); | ||
| 1468 | + } | ||
| 1469 | + engineConfigurations.put(key, engineConfiguration); | ||
| 1470 | + engineConfigurations.put(scopeType, engineConfiguration); | ||
| 1471 | + } | ||
| 1472 | + | ||
| 1473 | + public Map<String, AbstractServiceConfiguration> getServiceConfigurations() { | ||
| 1474 | + return serviceConfigurations; | ||
| 1475 | + } | ||
| 1476 | + | ||
| 1477 | + public AbstractEngineConfiguration setServiceConfigurations(Map<String, AbstractServiceConfiguration> serviceConfigurations) { | ||
| 1478 | + this.serviceConfigurations = serviceConfigurations; | ||
| 1479 | + return this; | ||
| 1480 | + } | ||
| 1481 | + | ||
| 1482 | + public void addServiceConfiguration(String key, AbstractServiceConfiguration serviceConfiguration) { | ||
| 1483 | + if (serviceConfigurations == null) { | ||
| 1484 | + serviceConfigurations = new HashMap<>(); | ||
| 1485 | + } | ||
| 1486 | + serviceConfigurations.put(key, serviceConfiguration); | ||
| 1487 | + } | ||
| 1488 | + | ||
| 1489 | + public Map<String, EventRegistryEventConsumer> getEventRegistryEventConsumers() { | ||
| 1490 | + return eventRegistryEventConsumers; | ||
| 1491 | + } | ||
| 1492 | + | ||
| 1493 | + public AbstractEngineConfiguration setEventRegistryEventConsumers(Map<String, EventRegistryEventConsumer> eventRegistryEventConsumers) { | ||
| 1494 | + this.eventRegistryEventConsumers = eventRegistryEventConsumers; | ||
| 1495 | + return this; | ||
| 1496 | + } | ||
| 1497 | + | ||
| 1498 | + public void addEventRegistryEventConsumer(String key, EventRegistryEventConsumer eventRegistryEventConsumer) { | ||
| 1499 | + if (eventRegistryEventConsumers == null) { | ||
| 1500 | + eventRegistryEventConsumers = new HashMap<>(); | ||
| 1501 | + } | ||
| 1502 | + eventRegistryEventConsumers.put(key, eventRegistryEventConsumer); | ||
| 1503 | + } | ||
| 1504 | + | ||
| 1505 | + public AbstractEngineConfiguration setDefaultCommandInterceptors(Collection<? extends CommandInterceptor> defaultCommandInterceptors) { | ||
| 1506 | + this.defaultCommandInterceptors = defaultCommandInterceptors; | ||
| 1507 | + return this; | ||
| 1508 | + } | ||
| 1509 | + | ||
| 1510 | + public SqlSessionFactory getSqlSessionFactory() { | ||
| 1511 | + return sqlSessionFactory; | ||
| 1512 | + } | ||
| 1513 | + | ||
| 1514 | + public AbstractEngineConfiguration setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { | ||
| 1515 | + this.sqlSessionFactory = sqlSessionFactory; | ||
| 1516 | + return this; | ||
| 1517 | + } | ||
| 1518 | + | ||
| 1519 | + public boolean isDbHistoryUsed() { | ||
| 1520 | + return isDbHistoryUsed; | ||
| 1521 | + } | ||
| 1522 | + | ||
| 1523 | + public AbstractEngineConfiguration setDbHistoryUsed(boolean isDbHistoryUsed) { | ||
| 1524 | + this.isDbHistoryUsed = isDbHistoryUsed; | ||
| 1525 | + return this; | ||
| 1526 | + } | ||
| 1527 | + | ||
| 1528 | + public DbSqlSessionFactory getDbSqlSessionFactory() { | ||
| 1529 | + return dbSqlSessionFactory; | ||
| 1530 | + } | ||
| 1531 | + | ||
| 1532 | + public AbstractEngineConfiguration setDbSqlSessionFactory(DbSqlSessionFactory dbSqlSessionFactory) { | ||
| 1533 | + this.dbSqlSessionFactory = dbSqlSessionFactory; | ||
| 1534 | + return this; | ||
| 1535 | + } | ||
| 1536 | + | ||
| 1537 | + public TransactionFactory getTransactionFactory() { | ||
| 1538 | + return transactionFactory; | ||
| 1539 | + } | ||
| 1540 | + | ||
| 1541 | + public AbstractEngineConfiguration setTransactionFactory(TransactionFactory transactionFactory) { | ||
| 1542 | + this.transactionFactory = transactionFactory; | ||
| 1543 | + return this; | ||
| 1544 | + } | ||
| 1545 | + | ||
| 1546 | + public TransactionContextFactory getTransactionContextFactory() { | ||
| 1547 | + return transactionContextFactory; | ||
| 1548 | + } | ||
| 1549 | + | ||
| 1550 | + public AbstractEngineConfiguration setTransactionContextFactory(TransactionContextFactory transactionContextFactory) { | ||
| 1551 | + this.transactionContextFactory = transactionContextFactory; | ||
| 1552 | + return this; | ||
| 1553 | + } | ||
| 1554 | + | ||
| 1555 | + public int getMaxNrOfStatementsInBulkInsert() { | ||
| 1556 | + return maxNrOfStatementsInBulkInsert; | ||
| 1557 | + } | ||
| 1558 | + | ||
| 1559 | + public AbstractEngineConfiguration setMaxNrOfStatementsInBulkInsert(int maxNrOfStatementsInBulkInsert) { | ||
| 1560 | + this.maxNrOfStatementsInBulkInsert = maxNrOfStatementsInBulkInsert; | ||
| 1561 | + return this; | ||
| 1562 | + } | ||
| 1563 | + | ||
| 1564 | + public boolean isBulkInsertEnabled() { | ||
| 1565 | + return isBulkInsertEnabled; | ||
| 1566 | + } | ||
| 1567 | + | ||
| 1568 | + public AbstractEngineConfiguration setBulkInsertEnabled(boolean isBulkInsertEnabled) { | ||
| 1569 | + this.isBulkInsertEnabled = isBulkInsertEnabled; | ||
| 1570 | + return this; | ||
| 1571 | + } | ||
| 1572 | + | ||
| 1573 | + public Set<Class<?>> getCustomMybatisMappers() { | ||
| 1574 | + return customMybatisMappers; | ||
| 1575 | + } | ||
| 1576 | + | ||
| 1577 | + public AbstractEngineConfiguration setCustomMybatisMappers(Set<Class<?>> customMybatisMappers) { | ||
| 1578 | + this.customMybatisMappers = customMybatisMappers; | ||
| 1579 | + return this; | ||
| 1580 | + } | ||
| 1581 | + | ||
| 1582 | + public Set<String> getCustomMybatisXMLMappers() { | ||
| 1583 | + return customMybatisXMLMappers; | ||
| 1584 | + } | ||
| 1585 | + | ||
| 1586 | + public AbstractEngineConfiguration setCustomMybatisXMLMappers(Set<String> customMybatisXMLMappers) { | ||
| 1587 | + this.customMybatisXMLMappers = customMybatisXMLMappers; | ||
| 1588 | + return this; | ||
| 1589 | + } | ||
| 1590 | + | ||
| 1591 | + public Set<String> getDependentEngineMyBatisXmlMappers() { | ||
| 1592 | + return dependentEngineMyBatisXmlMappers; | ||
| 1593 | + } | ||
| 1594 | + | ||
| 1595 | + public AbstractEngineConfiguration setCustomMybatisInterceptors(List<Interceptor> customMybatisInterceptors) { | ||
| 1596 | + this.customMybatisInterceptors = customMybatisInterceptors; | ||
| 1597 | + return this; | ||
| 1598 | + } | ||
| 1599 | + | ||
| 1600 | + public List<Interceptor> getCustomMybatisInterceptors() { | ||
| 1601 | + return customMybatisInterceptors; | ||
| 1602 | + } | ||
| 1603 | + | ||
| 1604 | + public AbstractEngineConfiguration setDependentEngineMyBatisXmlMappers(Set<String> dependentEngineMyBatisXmlMappers) { | ||
| 1605 | + this.dependentEngineMyBatisXmlMappers = dependentEngineMyBatisXmlMappers; | ||
| 1606 | + return this; | ||
| 1607 | + } | ||
| 1608 | + | ||
| 1609 | + public List<MybatisTypeAliasConfigurator> getDependentEngineMybatisTypeAliasConfigs() { | ||
| 1610 | + return dependentEngineMybatisTypeAliasConfigs; | ||
| 1611 | + } | ||
| 1612 | + | ||
| 1613 | + public AbstractEngineConfiguration setDependentEngineMybatisTypeAliasConfigs(List<MybatisTypeAliasConfigurator> dependentEngineMybatisTypeAliasConfigs) { | ||
| 1614 | + this.dependentEngineMybatisTypeAliasConfigs = dependentEngineMybatisTypeAliasConfigs; | ||
| 1615 | + return this; | ||
| 1616 | + } | ||
| 1617 | + | ||
| 1618 | + public List<MybatisTypeHandlerConfigurator> getDependentEngineMybatisTypeHandlerConfigs() { | ||
| 1619 | + return dependentEngineMybatisTypeHandlerConfigs; | ||
| 1620 | + } | ||
| 1621 | + | ||
| 1622 | + public AbstractEngineConfiguration setDependentEngineMybatisTypeHandlerConfigs(List<MybatisTypeHandlerConfigurator> dependentEngineMybatisTypeHandlerConfigs) { | ||
| 1623 | + this.dependentEngineMybatisTypeHandlerConfigs = dependentEngineMybatisTypeHandlerConfigs; | ||
| 1624 | + return this; | ||
| 1625 | + } | ||
| 1626 | + | ||
| 1627 | + public List<SessionFactory> getCustomSessionFactories() { | ||
| 1628 | + return customSessionFactories; | ||
| 1629 | + } | ||
| 1630 | + | ||
| 1631 | + public AbstractEngineConfiguration addCustomSessionFactory(SessionFactory sessionFactory) { | ||
| 1632 | + if (customSessionFactories == null) { | ||
| 1633 | + customSessionFactories = new ArrayList<>(); | ||
| 1634 | + } | ||
| 1635 | + customSessionFactories.add(sessionFactory); | ||
| 1636 | + return this; | ||
| 1637 | + } | ||
| 1638 | + | ||
| 1639 | + public AbstractEngineConfiguration setCustomSessionFactories(List<SessionFactory> customSessionFactories) { | ||
| 1640 | + this.customSessionFactories = customSessionFactories; | ||
| 1641 | + return this; | ||
| 1642 | + } | ||
| 1643 | + | ||
| 1644 | + public boolean isUsingRelationalDatabase() { | ||
| 1645 | + return usingRelationalDatabase; | ||
| 1646 | + } | ||
| 1647 | + | ||
| 1648 | + public AbstractEngineConfiguration setUsingRelationalDatabase(boolean usingRelationalDatabase) { | ||
| 1649 | + this.usingRelationalDatabase = usingRelationalDatabase; | ||
| 1650 | + return this; | ||
| 1651 | + } | ||
| 1652 | + | ||
| 1653 | + public boolean isUsingSchemaMgmt() { | ||
| 1654 | + return usingSchemaMgmt; | ||
| 1655 | + } | ||
| 1656 | + | ||
| 1657 | + public AbstractEngineConfiguration setUsingSchemaMgmt(boolean usingSchema) { | ||
| 1658 | + this.usingSchemaMgmt = usingSchema; | ||
| 1659 | + return this; | ||
| 1660 | + } | ||
| 1661 | + | ||
| 1662 | + public String getDatabaseTablePrefix() { | ||
| 1663 | + return databaseTablePrefix; | ||
| 1664 | + } | ||
| 1665 | + | ||
| 1666 | + public AbstractEngineConfiguration setDatabaseTablePrefix(String databaseTablePrefix) { | ||
| 1667 | + this.databaseTablePrefix = databaseTablePrefix; | ||
| 1668 | + return this; | ||
| 1669 | + } | ||
| 1670 | + | ||
| 1671 | + public String getDatabaseWildcardEscapeCharacter() { | ||
| 1672 | + return databaseWildcardEscapeCharacter; | ||
| 1673 | + } | ||
| 1674 | + | ||
| 1675 | + public AbstractEngineConfiguration setDatabaseWildcardEscapeCharacter(String databaseWildcardEscapeCharacter) { | ||
| 1676 | + this.databaseWildcardEscapeCharacter = databaseWildcardEscapeCharacter; | ||
| 1677 | + return this; | ||
| 1678 | + } | ||
| 1679 | + | ||
| 1680 | + public String getDatabaseCatalog() { | ||
| 1681 | + return databaseCatalog; | ||
| 1682 | + } | ||
| 1683 | + | ||
| 1684 | + public AbstractEngineConfiguration setDatabaseCatalog(String databaseCatalog) { | ||
| 1685 | + this.databaseCatalog = databaseCatalog; | ||
| 1686 | + return this; | ||
| 1687 | + } | ||
| 1688 | + | ||
| 1689 | + public String getDatabaseSchema() { | ||
| 1690 | + return databaseSchema; | ||
| 1691 | + } | ||
| 1692 | + | ||
| 1693 | + public AbstractEngineConfiguration setDatabaseSchema(String databaseSchema) { | ||
| 1694 | + this.databaseSchema = databaseSchema; | ||
| 1695 | + return this; | ||
| 1696 | + } | ||
| 1697 | + | ||
| 1698 | + public boolean isTablePrefixIsSchema() { | ||
| 1699 | + return tablePrefixIsSchema; | ||
| 1700 | + } | ||
| 1701 | + | ||
| 1702 | + public AbstractEngineConfiguration setTablePrefixIsSchema(boolean tablePrefixIsSchema) { | ||
| 1703 | + this.tablePrefixIsSchema = tablePrefixIsSchema; | ||
| 1704 | + return this; | ||
| 1705 | + } | ||
| 1706 | + | ||
| 1707 | + public boolean isAlwaysLookupLatestDefinitionVersion() { | ||
| 1708 | + return alwaysLookupLatestDefinitionVersion; | ||
| 1709 | + } | ||
| 1710 | + | ||
| 1711 | + public AbstractEngineConfiguration setAlwaysLookupLatestDefinitionVersion(boolean alwaysLookupLatestDefinitionVersion) { | ||
| 1712 | + this.alwaysLookupLatestDefinitionVersion = alwaysLookupLatestDefinitionVersion; | ||
| 1713 | + return this; | ||
| 1714 | + } | ||
| 1715 | + | ||
| 1716 | + public boolean isFallbackToDefaultTenant() { | ||
| 1717 | + return fallbackToDefaultTenant; | ||
| 1718 | + } | ||
| 1719 | + | ||
| 1720 | + public AbstractEngineConfiguration setFallbackToDefaultTenant(boolean fallbackToDefaultTenant) { | ||
| 1721 | + this.fallbackToDefaultTenant = fallbackToDefaultTenant; | ||
| 1722 | + return this; | ||
| 1723 | + } | ||
| 1724 | + | ||
| 1725 | + /** | ||
| 1726 | + * @return name of the default tenant | ||
| 1727 | + * @deprecated use {@link AbstractEngineConfiguration#getDefaultTenantProvider()} instead | ||
| 1728 | + */ | ||
| 1729 | + @Deprecated | ||
| 1730 | + public String getDefaultTenantValue() { | ||
| 1731 | + return getDefaultTenantProvider().getDefaultTenant(null, null, null); | ||
| 1732 | + } | ||
| 1733 | + | ||
| 1734 | + public AbstractEngineConfiguration setDefaultTenantValue(String defaultTenantValue) { | ||
| 1735 | + this.defaultTenantProvider = (tenantId, scope, scopeKey) -> defaultTenantValue; | ||
| 1736 | + return this; | ||
| 1737 | + } | ||
| 1738 | + | ||
| 1739 | + public DefaultTenantProvider getDefaultTenantProvider() { | ||
| 1740 | + return defaultTenantProvider; | ||
| 1741 | + } | ||
| 1742 | + | ||
| 1743 | + public AbstractEngineConfiguration setDefaultTenantProvider(DefaultTenantProvider defaultTenantProvider) { | ||
| 1744 | + this.defaultTenantProvider = defaultTenantProvider; | ||
| 1745 | + return this; | ||
| 1746 | + } | ||
| 1747 | + | ||
| 1748 | + public boolean isEnableLogSqlExecutionTime() { | ||
| 1749 | + return enableLogSqlExecutionTime; | ||
| 1750 | + } | ||
| 1751 | + | ||
| 1752 | + public void setEnableLogSqlExecutionTime(boolean enableLogSqlExecutionTime) { | ||
| 1753 | + this.enableLogSqlExecutionTime = enableLogSqlExecutionTime; | ||
| 1754 | + } | ||
| 1755 | + | ||
| 1756 | + public Map<Class<?>, SessionFactory> getSessionFactories() { | ||
| 1757 | + return sessionFactories; | ||
| 1758 | + } | ||
| 1759 | + | ||
| 1760 | + public AbstractEngineConfiguration setSessionFactories(Map<Class<?>, SessionFactory> sessionFactories) { | ||
| 1761 | + this.sessionFactories = sessionFactories; | ||
| 1762 | + return this; | ||
| 1763 | + } | ||
| 1764 | + | ||
| 1765 | + public String getDatabaseSchemaUpdate() { | ||
| 1766 | + return databaseSchemaUpdate; | ||
| 1767 | + } | ||
| 1768 | + | ||
| 1769 | + public AbstractEngineConfiguration setDatabaseSchemaUpdate(String databaseSchemaUpdate) { | ||
| 1770 | + this.databaseSchemaUpdate = databaseSchemaUpdate; | ||
| 1771 | + return this; | ||
| 1772 | + } | ||
| 1773 | + | ||
| 1774 | + public boolean isUseLockForDatabaseSchemaUpdate() { | ||
| 1775 | + return useLockForDatabaseSchemaUpdate; | ||
| 1776 | + } | ||
| 1777 | + | ||
| 1778 | + public AbstractEngineConfiguration setUseLockForDatabaseSchemaUpdate(boolean useLockForDatabaseSchemaUpdate) { | ||
| 1779 | + this.useLockForDatabaseSchemaUpdate = useLockForDatabaseSchemaUpdate; | ||
| 1780 | + return this; | ||
| 1781 | + } | ||
| 1782 | + | ||
| 1783 | + public boolean isEnableEventDispatcher() { | ||
| 1784 | + return enableEventDispatcher; | ||
| 1785 | + } | ||
| 1786 | + | ||
| 1787 | + public AbstractEngineConfiguration setEnableEventDispatcher(boolean enableEventDispatcher) { | ||
| 1788 | + this.enableEventDispatcher = enableEventDispatcher; | ||
| 1789 | + return this; | ||
| 1790 | + } | ||
| 1791 | + | ||
| 1792 | + public FlowableEventDispatcher getEventDispatcher() { | ||
| 1793 | + return eventDispatcher; | ||
| 1794 | + } | ||
| 1795 | + | ||
| 1796 | + public AbstractEngineConfiguration setEventDispatcher(FlowableEventDispatcher eventDispatcher) { | ||
| 1797 | + this.eventDispatcher = eventDispatcher; | ||
| 1798 | + return this; | ||
| 1799 | + } | ||
| 1800 | + | ||
| 1801 | + public List<FlowableEventListener> getEventListeners() { | ||
| 1802 | + return eventListeners; | ||
| 1803 | + } | ||
| 1804 | + | ||
| 1805 | + public AbstractEngineConfiguration setEventListeners(List<FlowableEventListener> eventListeners) { | ||
| 1806 | + this.eventListeners = eventListeners; | ||
| 1807 | + return this; | ||
| 1808 | + } | ||
| 1809 | + | ||
| 1810 | + public Map<String, List<FlowableEventListener>> getTypedEventListeners() { | ||
| 1811 | + return typedEventListeners; | ||
| 1812 | + } | ||
| 1813 | + | ||
| 1814 | + public AbstractEngineConfiguration setTypedEventListeners(Map<String, List<FlowableEventListener>> typedEventListeners) { | ||
| 1815 | + this.typedEventListeners = typedEventListeners; | ||
| 1816 | + return this; | ||
| 1817 | + } | ||
| 1818 | + | ||
| 1819 | + public List<EventDispatchAction> getAdditionalEventDispatchActions() { | ||
| 1820 | + return additionalEventDispatchActions; | ||
| 1821 | + } | ||
| 1822 | + | ||
| 1823 | + public AbstractEngineConfiguration setAdditionalEventDispatchActions(List<EventDispatchAction> additionalEventDispatchActions) { | ||
| 1824 | + this.additionalEventDispatchActions = additionalEventDispatchActions; | ||
| 1825 | + return this; | ||
| 1826 | + } | ||
| 1827 | + | ||
| 1828 | + public void initEventDispatcher() { | ||
| 1829 | + if (this.eventDispatcher == null) { | ||
| 1830 | + this.eventDispatcher = new FlowableEventDispatcherImpl(); | ||
| 1831 | + } | ||
| 1832 | + | ||
| 1833 | + initAdditionalEventDispatchActions(); | ||
| 1834 | + | ||
| 1835 | + this.eventDispatcher.setEnabled(enableEventDispatcher); | ||
| 1836 | + | ||
| 1837 | + initEventListeners(); | ||
| 1838 | + initTypedEventListeners(); | ||
| 1839 | + } | ||
| 1840 | + | ||
| 1841 | + protected void initEventListeners() { | ||
| 1842 | + if (eventListeners != null) { | ||
| 1843 | + for (FlowableEventListener listenerToAdd : eventListeners) { | ||
| 1844 | + this.eventDispatcher.addEventListener(listenerToAdd); | ||
| 1845 | + } | ||
| 1846 | + } | ||
| 1847 | + } | ||
| 1848 | + | ||
| 1849 | + protected void initAdditionalEventDispatchActions() { | ||
| 1850 | + if (this.additionalEventDispatchActions == null) { | ||
| 1851 | + this.additionalEventDispatchActions = new ArrayList<>(); | ||
| 1852 | + } | ||
| 1853 | + } | ||
| 1854 | + | ||
| 1855 | + protected void initTypedEventListeners() { | ||
| 1856 | + if (typedEventListeners != null) { | ||
| 1857 | + for (Map.Entry<String, List<FlowableEventListener>> listenersToAdd : typedEventListeners.entrySet()) { | ||
| 1858 | + // Extract types from the given string | ||
| 1859 | + FlowableEngineEventType[] types = FlowableEngineEventType.getTypesFromString(listenersToAdd.getKey()); | ||
| 1860 | + | ||
| 1861 | + for (FlowableEventListener listenerToAdd : listenersToAdd.getValue()) { | ||
| 1862 | + this.eventDispatcher.addEventListener(listenerToAdd, types); | ||
| 1863 | + } | ||
| 1864 | + } | ||
| 1865 | + } | ||
| 1866 | + } | ||
| 1867 | + | ||
| 1868 | + public boolean isLoggingSessionEnabled() { | ||
| 1869 | + return loggingListener != null; | ||
| 1870 | + } | ||
| 1871 | + | ||
| 1872 | + public LoggingListener getLoggingListener() { | ||
| 1873 | + return loggingListener; | ||
| 1874 | + } | ||
| 1875 | + | ||
| 1876 | + public void setLoggingListener(LoggingListener loggingListener) { | ||
| 1877 | + this.loggingListener = loggingListener; | ||
| 1878 | + } | ||
| 1879 | + | ||
| 1880 | + public Clock getClock() { | ||
| 1881 | + return clock; | ||
| 1882 | + } | ||
| 1883 | + | ||
| 1884 | + public AbstractEngineConfiguration setClock(Clock clock) { | ||
| 1885 | + this.clock = clock; | ||
| 1886 | + return this; | ||
| 1887 | + } | ||
| 1888 | + | ||
| 1889 | + public ObjectMapper getObjectMapper() { | ||
| 1890 | + return objectMapper; | ||
| 1891 | + } | ||
| 1892 | + | ||
| 1893 | + public AbstractEngineConfiguration setObjectMapper(ObjectMapper objectMapper) { | ||
| 1894 | + this.objectMapper = objectMapper; | ||
| 1895 | + return this; | ||
| 1896 | + } | ||
| 1897 | + | ||
| 1898 | + public int getMaxLengthString() { | ||
| 1899 | + if (maxLengthStringVariableType == -1) { | ||
| 1900 | + if ("oracle".equalsIgnoreCase(databaseType)) { | ||
| 1901 | + return DEFAULT_ORACLE_MAX_LENGTH_STRING; | ||
| 1902 | + } else { | ||
| 1903 | + return DEFAULT_GENERIC_MAX_LENGTH_STRING; | ||
| 1904 | + } | ||
| 1905 | + } else { | ||
| 1906 | + return maxLengthStringVariableType; | ||
| 1907 | + } | ||
| 1908 | + } | ||
| 1909 | + | ||
| 1910 | + public int getMaxLengthStringVariableType() { | ||
| 1911 | + return maxLengthStringVariableType; | ||
| 1912 | + } | ||
| 1913 | + | ||
| 1914 | + public AbstractEngineConfiguration setMaxLengthStringVariableType(int maxLengthStringVariableType) { | ||
| 1915 | + this.maxLengthStringVariableType = maxLengthStringVariableType; | ||
| 1916 | + return this; | ||
| 1917 | + } | ||
| 1918 | + | ||
| 1919 | + public PropertyDataManager getPropertyDataManager() { | ||
| 1920 | + return propertyDataManager; | ||
| 1921 | + } | ||
| 1922 | + | ||
| 1923 | + public Duration getLockPollRate() { | ||
| 1924 | + return lockPollRate; | ||
| 1925 | + } | ||
| 1926 | + | ||
| 1927 | + public AbstractEngineConfiguration setLockPollRate(Duration lockPollRate) { | ||
| 1928 | + this.lockPollRate = lockPollRate; | ||
| 1929 | + return this; | ||
| 1930 | + } | ||
| 1931 | + | ||
| 1932 | + public Duration getSchemaLockWaitTime() { | ||
| 1933 | + return schemaLockWaitTime; | ||
| 1934 | + } | ||
| 1935 | + | ||
| 1936 | + public void setSchemaLockWaitTime(Duration schemaLockWaitTime) { | ||
| 1937 | + this.schemaLockWaitTime = schemaLockWaitTime; | ||
| 1938 | + } | ||
| 1939 | + | ||
| 1940 | + public AbstractEngineConfiguration setPropertyDataManager(PropertyDataManager propertyDataManager) { | ||
| 1941 | + this.propertyDataManager = propertyDataManager; | ||
| 1942 | + return this; | ||
| 1943 | + } | ||
| 1944 | + | ||
| 1945 | + public PropertyEntityManager getPropertyEntityManager() { | ||
| 1946 | + return propertyEntityManager; | ||
| 1947 | + } | ||
| 1948 | + | ||
| 1949 | + public AbstractEngineConfiguration setPropertyEntityManager(PropertyEntityManager propertyEntityManager) { | ||
| 1950 | + this.propertyEntityManager = propertyEntityManager; | ||
| 1951 | + return this; | ||
| 1952 | + } | ||
| 1953 | + | ||
| 1954 | + public ByteArrayDataManager getByteArrayDataManager() { | ||
| 1955 | + return byteArrayDataManager; | ||
| 1956 | + } | ||
| 1957 | + | ||
| 1958 | + public AbstractEngineConfiguration setByteArrayDataManager(ByteArrayDataManager byteArrayDataManager) { | ||
| 1959 | + this.byteArrayDataManager = byteArrayDataManager; | ||
| 1960 | + return this; | ||
| 1961 | + } | ||
| 1962 | + | ||
| 1963 | + public ByteArrayEntityManager getByteArrayEntityManager() { | ||
| 1964 | + return byteArrayEntityManager; | ||
| 1965 | + } | ||
| 1966 | + | ||
| 1967 | + public AbstractEngineConfiguration setByteArrayEntityManager(ByteArrayEntityManager byteArrayEntityManager) { | ||
| 1968 | + this.byteArrayEntityManager = byteArrayEntityManager; | ||
| 1969 | + return this; | ||
| 1970 | + } | ||
| 1971 | + | ||
| 1972 | + public TableDataManager getTableDataManager() { | ||
| 1973 | + return tableDataManager; | ||
| 1974 | + } | ||
| 1975 | + | ||
| 1976 | + public AbstractEngineConfiguration setTableDataManager(TableDataManager tableDataManager) { | ||
| 1977 | + this.tableDataManager = tableDataManager; | ||
| 1978 | + return this; | ||
| 1979 | + } | ||
| 1980 | + | ||
| 1981 | + public List<EngineDeployer> getDeployers() { | ||
| 1982 | + return deployers; | ||
| 1983 | + } | ||
| 1984 | + | ||
| 1985 | + public AbstractEngineConfiguration setDeployers(List<EngineDeployer> deployers) { | ||
| 1986 | + this.deployers = deployers; | ||
| 1987 | + return this; | ||
| 1988 | + } | ||
| 1989 | + | ||
| 1990 | + public List<EngineDeployer> getCustomPreDeployers() { | ||
| 1991 | + return customPreDeployers; | ||
| 1992 | + } | ||
| 1993 | + | ||
| 1994 | + public AbstractEngineConfiguration setCustomPreDeployers(List<EngineDeployer> customPreDeployers) { | ||
| 1995 | + this.customPreDeployers = customPreDeployers; | ||
| 1996 | + return this; | ||
| 1997 | + } | ||
| 1998 | + | ||
| 1999 | + public List<EngineDeployer> getCustomPostDeployers() { | ||
| 2000 | + return customPostDeployers; | ||
| 2001 | + } | ||
| 2002 | + | ||
| 2003 | + public AbstractEngineConfiguration setCustomPostDeployers(List<EngineDeployer> customPostDeployers) { | ||
| 2004 | + this.customPostDeployers = customPostDeployers; | ||
| 2005 | + return this; | ||
| 2006 | + } | ||
| 2007 | + | ||
| 2008 | + public boolean isEnableConfiguratorServiceLoader() { | ||
| 2009 | + return enableConfiguratorServiceLoader; | ||
| 2010 | + } | ||
| 2011 | + | ||
| 2012 | + public AbstractEngineConfiguration setEnableConfiguratorServiceLoader(boolean enableConfiguratorServiceLoader) { | ||
| 2013 | + this.enableConfiguratorServiceLoader = enableConfiguratorServiceLoader; | ||
| 2014 | + return this; | ||
| 2015 | + } | ||
| 2016 | + | ||
| 2017 | + public List<EngineConfigurator> getConfigurators() { | ||
| 2018 | + return configurators; | ||
| 2019 | + } | ||
| 2020 | + | ||
| 2021 | + public AbstractEngineConfiguration addConfigurator(EngineConfigurator configurator) { | ||
| 2022 | + if (configurators == null) { | ||
| 2023 | + configurators = new ArrayList<>(); | ||
| 2024 | + } | ||
| 2025 | + configurators.add(configurator); | ||
| 2026 | + return this; | ||
| 2027 | + } | ||
| 2028 | + | ||
| 2029 | + /** | ||
| 2030 | + * @return All {@link EngineConfigurator} instances. Will only contain values after init of the engine. | ||
| 2031 | + * Use the {@link #getConfigurators()} or {@link #addConfigurator(EngineConfigurator)} methods otherwise. | ||
| 2032 | + */ | ||
| 2033 | + public List<EngineConfigurator> getAllConfigurators() { | ||
| 2034 | + return allConfigurators; | ||
| 2035 | + } | ||
| 2036 | + | ||
| 2037 | + public AbstractEngineConfiguration setConfigurators(List<EngineConfigurator> configurators) { | ||
| 2038 | + this.configurators = configurators; | ||
| 2039 | + return this; | ||
| 2040 | + } | ||
| 2041 | + | ||
| 2042 | + public EngineConfigurator getIdmEngineConfigurator() { | ||
| 2043 | + return idmEngineConfigurator; | ||
| 2044 | + } | ||
| 2045 | + | ||
| 2046 | + public AbstractEngineConfiguration setIdmEngineConfigurator(EngineConfigurator idmEngineConfigurator) { | ||
| 2047 | + this.idmEngineConfigurator = idmEngineConfigurator; | ||
| 2048 | + return this; | ||
| 2049 | + } | ||
| 2050 | + | ||
| 2051 | + public EngineConfigurator getEventRegistryConfigurator() { | ||
| 2052 | + return eventRegistryConfigurator; | ||
| 2053 | + } | ||
| 2054 | + | ||
| 2055 | + public AbstractEngineConfiguration setEventRegistryConfigurator(EngineConfigurator eventRegistryConfigurator) { | ||
| 2056 | + this.eventRegistryConfigurator = eventRegistryConfigurator; | ||
| 2057 | + return this; | ||
| 2058 | + } | ||
| 2059 | + | ||
| 2060 | + public AbstractEngineConfiguration setForceCloseMybatisConnectionPool(boolean forceCloseMybatisConnectionPool) { | ||
| 2061 | + this.forceCloseMybatisConnectionPool = forceCloseMybatisConnectionPool; | ||
| 2062 | + return this; | ||
| 2063 | + } | ||
| 2064 | + | ||
| 2065 | + public boolean isForceCloseMybatisConnectionPool() { | ||
| 2066 | + return forceCloseMybatisConnectionPool; | ||
| 2067 | + } | ||
| 2068 | +} |
sql/dm/flowable-patch/src/main/resources/META-INF/package-info.md
0 → 100644
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 |