diff --git a/sql/db2/flowable-patch/src/main/java/liquibase/database/core/DmDatabase.java b/sql/db2/flowable-patch/src/main/java/liquibase/database/core/DmDatabase.java deleted file mode 100644 index fbc4c6bc1..000000000 --- a/sql/db2/flowable-patch/src/main/java/liquibase/database/core/DmDatabase.java +++ /dev/null @@ -1,598 +0,0 @@ -package liquibase.database.core; - -import java.lang.reflect.Method; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import liquibase.CatalogAndSchema; -import liquibase.Scope; -import liquibase.database.AbstractJdbcDatabase; -import liquibase.database.DatabaseConnection; -import liquibase.database.OfflineConnection; -import liquibase.database.jvm.JdbcConnection; -import liquibase.exception.DatabaseException; -import liquibase.exception.UnexpectedLiquibaseException; -import liquibase.exception.ValidationErrors; -import liquibase.executor.ExecutorService; -import liquibase.statement.DatabaseFunction; -import liquibase.statement.SequenceCurrentValueFunction; -import liquibase.statement.SequenceNextValueFunction; -import liquibase.statement.core.RawCallStatement; -import liquibase.statement.core.RawSqlStatement; -import liquibase.structure.DatabaseObject; -import liquibase.structure.core.Catalog; -import liquibase.structure.core.Index; -import liquibase.structure.core.PrimaryKey; -import liquibase.structure.core.Schema; -import liquibase.util.JdbcUtils; -import liquibase.util.StringUtil; - -public class DmDatabase extends AbstractJdbcDatabase { - private static final String PRODUCT_NAME = "DM DBMS"; - - @Override - protected String getDefaultDatabaseProductName() { - return PRODUCT_NAME; - } - - /** - * Is this AbstractDatabase subclass the correct one to use for the given connection. - * - * @param conn - */ - @Override - public boolean isCorrectDatabaseImplementation(DatabaseConnection conn) throws DatabaseException { - return PRODUCT_NAME.equalsIgnoreCase(conn.getDatabaseProductName()); - } - - /** - * If this database understands the given url, return the default driver class name. Otherwise return null. - * - * @param url - */ - @Override - public String getDefaultDriver(String url) { - if(url.startsWith("jdbc:dm")) { - return "dm.jdbc.driver.DmDriver"; - } - - return null; - } - - /** - * Returns an all-lower-case short name of the product. Used for end-user selecting of database type - * such as the DBMS precondition. - */ - @Override - public String getShortName() { - return "dm"; - } - - @Override - public Integer getDefaultPort() { - return 5236; - } - - /** - * Returns whether this database support initially deferrable columns. - */ - @Override - public boolean supportsInitiallyDeferrableColumns() { - return true; - } - - @Override - public boolean supportsTablespaces() { - return true; - } - - @Override - public int getPriority() { - return PRIORITY_DEFAULT; - } - - private static final Pattern PROXY_USER = Pattern.compile(".*(?:thin|oci)\\:(.+)/@.*"); - - protected final int SHORT_IDENTIFIERS_LENGTH = 30; - protected final int LONG_IDENTIFIERS_LEGNTH = 128; - public static final int ORACLE_12C_MAJOR_VERSION = 12; - - private Set reservedWords = new HashSet<>(); - private Set userDefinedTypes; - private Map savedSessionNlsSettings; - - private Boolean canAccessDbaRecycleBin; - private Integer databaseMajorVersion; - private Integer databaseMinorVersion; - - /** - * Default constructor for an object that represents the Oracle Database DBMS. - */ - public DmDatabase() { - super.unquotedObjectsAreUppercased = true; - //noinspection HardCodedStringLiteral - super.setCurrentDateTimeFunction("SYSTIMESTAMP"); - // Setting list of Oracle's native functions - //noinspection HardCodedStringLiteral - dateFunctions.add(new DatabaseFunction("SYSDATE")); - //noinspection HardCodedStringLiteral - dateFunctions.add(new DatabaseFunction("SYSTIMESTAMP")); - //noinspection HardCodedStringLiteral - dateFunctions.add(new DatabaseFunction("CURRENT_TIMESTAMP")); - //noinspection HardCodedStringLiteral - super.sequenceNextValueFunction = "%s.nextval"; - //noinspection HardCodedStringLiteral - super.sequenceCurrentValueFunction = "%s.currval"; - } - - private void tryProxySession(final String url, final Connection con) { - Matcher m = PROXY_USER.matcher(url); - if (m.matches()) { - Properties props = new Properties(); - props.put("PROXY_USER_NAME", m.group(1)); - try { - Method method = con.getClass().getMethod("openProxySession", int.class, Properties.class); - method.setAccessible(true); - method.invoke(con, 1, props); - } catch (Exception e) { - Scope.getCurrentScope().getLog(getClass()).info("Could not open proxy session on OracleDatabase: " + e.getCause().getMessage()); - } - } - } - - @Override - public int getDatabaseMajorVersion() throws DatabaseException { - if (databaseMajorVersion == null) { - return super.getDatabaseMajorVersion(); - } else { - return databaseMajorVersion; - } - } - - @Override - public int getDatabaseMinorVersion() throws DatabaseException { - if (databaseMinorVersion == null) { - return super.getDatabaseMinorVersion(); - } else { - return databaseMinorVersion; - } - } - - @Override - public String getJdbcCatalogName(CatalogAndSchema schema) { - return null; - } - - @Override - public String getJdbcSchemaName(CatalogAndSchema schema) { - return correctObjectName((schema.getCatalogName() == null) ? schema.getSchemaName() : schema.getCatalogName(), Schema.class); - } - - @Override - protected String getAutoIncrementClause(final String generationType, final Boolean defaultOnNull) { - if (StringUtil.isEmpty(generationType)) { - return super.getAutoIncrementClause(); - } - - String autoIncrementClause = "GENERATED %s AS IDENTITY"; // %s -- [ ALWAYS | BY DEFAULT [ ON NULL ] ] - String generationStrategy = generationType; - if (Boolean.TRUE.equals(defaultOnNull) && generationType.toUpperCase().equals("BY DEFAULT")) { - generationStrategy += " ON NULL"; - } - return String.format(autoIncrementClause, generationStrategy); - } - - @Override - public String generatePrimaryKeyName(String tableName) { - if (tableName.length() > 27) { - //noinspection HardCodedStringLiteral - return "PK_" + tableName.toUpperCase(Locale.US).substring(0, 27); - } else { - //noinspection HardCodedStringLiteral - return "PK_" + tableName.toUpperCase(Locale.US); - } - } - - @Override - public boolean isReservedWord(String objectName) { - return reservedWords.contains(objectName.toUpperCase()); - } - - @Override - public boolean supportsSequences() { - return true; - } - - /** - * Oracle supports catalogs in liquibase terms - * - * @return false - */ - @Override - public boolean supportsSchemas() { - return false; - } - - @Override - protected String getConnectionCatalogName() throws DatabaseException { - if (getConnection() instanceof OfflineConnection) { - return getConnection().getCatalog(); - } - try { - //noinspection HardCodedStringLiteral - return Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForObject(new RawCallStatement("select sys_context( 'userenv', 'current_schema' ) from dual"), String.class); - } catch (Exception e) { - //noinspection HardCodedStringLiteral - Scope.getCurrentScope().getLog(getClass()).info("Error getting default schema", e); - } - return null; - } - - @Override - public String getDefaultCatalogName() {//NOPMD - return (super.getDefaultCatalogName() == null) ? null : super.getDefaultCatalogName().toUpperCase(Locale.US); - } - - /** - *

Returns an Oracle date literal with the same value as a string formatted using ISO 8601.

- * - *

Convert an ISO8601 date string to one of the following results: - * to_date('1995-05-23', 'YYYY-MM-DD') - * to_date('1995-05-23 09:23:59', 'YYYY-MM-DD HH24:MI:SS')

- *

- * Implementation restriction:
- * Currently, only the following subsets of ISO8601 are supported:
- *

    - *
  • YYYY-MM-DD
  • - *
  • YYYY-MM-DDThh:mm:ss
  • - *
- */ - @Override - public String getDateLiteral(String isoDate) { - String normalLiteral = super.getDateLiteral(isoDate); - - if (isDateOnly(isoDate)) { - return "TO_DATE(" + normalLiteral + ", 'YYYY-MM-DD')"; - } else if (isTimeOnly(isoDate)) { - return "TO_DATE(" + normalLiteral + ", 'HH24:MI:SS')"; - } else if (isTimestamp(isoDate)) { - return "TO_TIMESTAMP(" + normalLiteral + ", 'YYYY-MM-DD HH24:MI:SS.FF')"; - } else if (isDateTime(isoDate)) { - int seppos = normalLiteral.lastIndexOf('.'); - if (seppos != -1) { - normalLiteral = normalLiteral.substring(0, seppos) + "'"; - } - return "TO_DATE(" + normalLiteral + ", 'YYYY-MM-DD HH24:MI:SS')"; - } - return "UNSUPPORTED:" + isoDate; - } - - @Override - public boolean isSystemObject(DatabaseObject example) { - if (example == null) { - return false; - } - - if (this.isLiquibaseObject(example)) { - return false; - } - - if (example instanceof Schema) { - //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral - if ("SYSTEM".equals(example.getName()) || "SYS".equals(example.getName()) || "CTXSYS".equals(example.getName()) || "XDB".equals(example.getName())) { - return true; - } - //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral - if ("SYSTEM".equals(example.getSchema().getCatalogName()) || "SYS".equals(example.getSchema().getCatalogName()) || "CTXSYS".equals(example.getSchema().getCatalogName()) || "XDB".equals(example.getSchema().getCatalogName())) { - return true; - } - } else if (isSystemObject(example.getSchema())) { - return true; - } - if (example instanceof Catalog) { - //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral - if (("SYSTEM".equals(example.getName()) || "SYS".equals(example.getName()) || "CTXSYS".equals(example.getName()) || "XDB".equals(example.getName()))) { - return true; - } - } else if (example.getName() != null) { - //noinspection HardCodedStringLiteral - if (example.getName().startsWith("BIN$")) { //oracle deleted table - boolean filteredInOriginalQuery = this.canAccessDbaRecycleBin(); - if (!filteredInOriginalQuery) { - filteredInOriginalQuery = StringUtil.trimToEmpty(example.getSchema().getName()).equalsIgnoreCase(this.getConnection().getConnectionUserName()); - } - - if (filteredInOriginalQuery) { - return !((example instanceof PrimaryKey) || (example instanceof Index) || (example instanceof - liquibase.statement.UniqueConstraint)); - } else { - return true; - } - } else //noinspection HardCodedStringLiteral - if (example.getName().startsWith("AQ$")) { //oracle AQ tables - return true; - } else //noinspection HardCodedStringLiteral - if (example.getName().startsWith("DR$")) { //oracle index tables - return true; - } else //noinspection HardCodedStringLiteral - if (example.getName().startsWith("SYS_IOT_OVER")) { //oracle system table - return true; - } else //noinspection HardCodedStringLiteral,HardCodedStringLiteral - if ((example.getName().startsWith("MDRT_") || example.getName().startsWith("MDRS_")) && example.getName().endsWith("$")) { - // CORE-1768 - Oracle creates these for spatial indices and will remove them when the index is removed. - return true; - } else //noinspection HardCodedStringLiteral - 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. - return true; - } else //noinspection HardCodedStringLiteral - if (example.getName().startsWith("RUPD$_")) { //Created by materialized view log tables using primary keys. Not available for DDL operations. - return true; - } else //noinspection HardCodedStringLiteral - if (example.getName().startsWith("WM$_")) { //Workspace Manager backup tables. - return true; - } else //noinspection HardCodedStringLiteral - 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. - return true; - } else //noinspection HardCodedStringLiteral - if ("JAVA$CLASS$MD5$TABLE".equals(example.getName())) { //This is a hash table that tracks the loading of Java objects into a schema. - return true; - } else //noinspection HardCodedStringLiteral - if (example.getName().startsWith("ISEQ$$_")) { //System-generated sequence - return true; - } else //noinspection HardCodedStringLiteral - if (example.getName().startsWith("USLOG$")) { //for update materialized view - return true; - } else if (example.getName().startsWith("SYS_FBA")) { //for Flashback tables - return true; - } - } - - return super.isSystemObject(example); - } - - @Override - public boolean supportsAutoIncrement() { - // Oracle supports Identity beginning with version 12c - boolean isAutoIncrementSupported = false; - - try { - if (getDatabaseMajorVersion() >= 12) { - isAutoIncrementSupported = true; - } - - // Returning true will generate create table command with 'IDENTITY' clause, example: - // 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)); - - // While returning false will continue to generate create table command without 'IDENTITY' clause, example: - // CREATE TABLE AutoIncTest (IDPrimaryKey NUMBER(19) NOT NULL, TypeID NUMBER(3) NOT NULL, Description NVARCHAR2(50), CONSTRAINT PK_AutoIncTest PRIMARY KEY (IDPrimaryKey)); - - } catch (DatabaseException ex) { - isAutoIncrementSupported = false; - } - - return isAutoIncrementSupported; - } - - -// public Set findUniqueConstraints(String schema) throws DatabaseException { -// Set returnSet = new HashSet(); -// -// List 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")); -// -// UniqueConstraint constraint = null; -// for (Map map : maps) { -// if (constraint == null || !constraint.getName().equals(constraint.getName())) { -// returnSet.add(constraint); -// Table table = new Table((String) map.get("TABLE_NAME")); -// constraint = new UniqueConstraint(map.get("CONSTRAINT_NAME").toString(), table); -// } -// } -// if (constraint != null) { -// returnSet.add(constraint); -// } -// -// return returnSet; -// } - - @Override - public boolean supportsRestrictForeignKeys() { - return false; - } - - @Override - public int getDataTypeMaxParameters(String dataTypeName) { - //noinspection HardCodedStringLiteral - if ("BINARY_FLOAT".equals(dataTypeName.toUpperCase())) { - return 0; - } - //noinspection HardCodedStringLiteral - if ("BINARY_DOUBLE".equals(dataTypeName.toUpperCase())) { - return 0; - } - return super.getDataTypeMaxParameters(dataTypeName); - } - - public String getSystemTableWhereClause(String tableNameColumn) { - List clauses = new ArrayList(Arrays.asList("BIN$", - "AQ$", - "DR$", - "SYS_IOT_OVER", - "MLOG$_", - "RUPD$_", - "WM$_", - "ISEQ$$_", - "USLOG$", - "SYS_FBA")); - - for (int i = 0;i getUserDefinedTypes() { - if (userDefinedTypes == null) { - userDefinedTypes = new HashSet<>(); - if ((getConnection() != null) && !(getConnection() instanceof OfflineConnection)) { - try { - try { - //noinspection HardCodedStringLiteral - userDefinedTypes.addAll(Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForList(new RawSqlStatement("SELECT DISTINCT TYPE_NAME FROM ALL_TYPES"), String.class)); - } catch (DatabaseException e) { //fall back to USER_TYPES if the user cannot see ALL_TYPES - //noinspection HardCodedStringLiteral - userDefinedTypes.addAll(Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForList(new RawSqlStatement("SELECT TYPE_NAME FROM USER_TYPES"), String.class)); - } - } catch (DatabaseException e) { - //ignore error - } - } - } - - return userDefinedTypes; - } - - @Override - public String generateDatabaseFunctionValue(DatabaseFunction databaseFunction) { - //noinspection HardCodedStringLiteral - if ((databaseFunction != null) && "current_timestamp".equalsIgnoreCase(databaseFunction.toString())) { - return databaseFunction.toString(); - } - if ((databaseFunction instanceof SequenceNextValueFunction) || (databaseFunction instanceof - SequenceCurrentValueFunction)) { - String quotedSeq = super.generateDatabaseFunctionValue(databaseFunction); - // replace "myschema.my_seq".nextval with "myschema"."my_seq".nextval - return quotedSeq.replaceFirst("\"([^\\.\"]+)\\.([^\\.\"]+)\"", "\"$1\".\"$2\""); - - } - - return super.generateDatabaseFunctionValue(databaseFunction); - } - - @Override - public ValidationErrors validate() { - ValidationErrors errors = super.validate(); - DatabaseConnection connection = getConnection(); - if ((connection == null) || (connection instanceof OfflineConnection)) { - //noinspection HardCodedStringLiteral - Scope.getCurrentScope().getLog(getClass()).info("Cannot validate offline database"); - return errors; - } - - if (!canAccessDbaRecycleBin()) { - errors.addWarning(getDbaRecycleBinWarning()); - } - - return errors; - - } - - public String getDbaRecycleBinWarning() { - //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral, - // HardCodedStringLiteral - //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral - return "Liquibase needs to access the DBA_RECYCLEBIN table so we can automatically handle the case where " + - "constraints are deleted and restored. Since Oracle doesn't properly restore the original table names " + - "referenced in the constraint, we use the information from the DBA_RECYCLEBIN to automatically correct this" + - " issue.\n" + - "\n" + - "The user you used to connect to the database (" + getConnection().getConnectionUserName() + - ") needs to have \"SELECT ON SYS.DBA_RECYCLEBIN\" permissions set before we can perform this operation. " + - "Please run the following SQL to set the appropriate permissions, and try running the command again.\n" + - "\n" + - " GRANT SELECT ON SYS.DBA_RECYCLEBIN TO " + getConnection().getConnectionUserName() + ";"; - } - - public boolean canAccessDbaRecycleBin() { - if (canAccessDbaRecycleBin == null) { - DatabaseConnection connection = getConnection(); - if ((connection == null) || (connection instanceof OfflineConnection)) { - return false; - } - - Statement statement = null; - try { - statement = ((JdbcConnection) connection).createStatement(); - @SuppressWarnings("HardCodedStringLiteral") ResultSet resultSet = statement.executeQuery("select 1 from dba_recyclebin where 0=1"); - resultSet.close(); //don't need to do anything with the result set, just make sure statement ran. - this.canAccessDbaRecycleBin = true; - } catch (Exception e) { - //noinspection HardCodedStringLiteral - if ((e instanceof SQLException) && e.getMessage().startsWith("ORA-00942")) { //ORA-00942: table or view does not exist - this.canAccessDbaRecycleBin = false; - } else { - //noinspection HardCodedStringLiteral - Scope.getCurrentScope().getLog(getClass()).warning("Cannot check dba_recyclebin access", e); - this.canAccessDbaRecycleBin = false; - } - } finally { - JdbcUtils.close(null, statement); - } - } - - return canAccessDbaRecycleBin; - } - - @Override - public boolean supportsNotNullConstraintNames() { - return true; - } - - /** - * Tests if the given String would be a valid identifier in Oracle DBMS. In Oracle, a valid identifier has - * the following form (case-insensitive comparison): - * 1st character: A-Z - * 2..n characters: A-Z0-9$_# - * The maximum length of an identifier differs by Oracle version and object type. - */ - public boolean isValidOracleIdentifier(String identifier, Class type) { - if ((identifier == null) || (identifier.length() < 1)) - return false; - - if (!identifier.matches("^(i?)[A-Z][A-Z0-9\\$\\_\\#]*$")) - return false; - - /* - * @todo It seems we currently do not have a class for tablespace identifiers, and all other classes - * we do know seem to be supported as 12cR2 long identifiers, so: - */ - return (identifier.length() <= LONG_IDENTIFIERS_LEGNTH); - } - - /** - * Returns the maximum number of bytes (NOT: characters) for an identifier. For Oracle <=12c Release 20, this - * is 30 bytes, and starting from 12cR2, up to 128 (except for tablespaces, PDB names and some other rather rare - * object types). - * - * @return the maximum length of an object identifier, in bytes - */ - public int getIdentifierMaximumLength() { - try { - if (getDatabaseMajorVersion() < ORACLE_12C_MAJOR_VERSION) { - return SHORT_IDENTIFIERS_LENGTH; - } else if ((getDatabaseMajorVersion() == ORACLE_12C_MAJOR_VERSION) && (getDatabaseMinorVersion() <= 1)) { - return SHORT_IDENTIFIERS_LENGTH; - } else { - return LONG_IDENTIFIERS_LEGNTH; - } - } catch (DatabaseException ex) { - throw new UnexpectedLiquibaseException("Cannot determine the Oracle database version number", ex); - } - - } -} diff --git a/sql/db2/flowable-patch/src/main/java/liquibase/datatype/core/BooleanType.java b/sql/db2/flowable-patch/src/main/java/liquibase/datatype/core/BooleanType.java deleted file mode 100644 index cda2492e2..000000000 --- a/sql/db2/flowable-patch/src/main/java/liquibase/datatype/core/BooleanType.java +++ /dev/null @@ -1,165 +0,0 @@ -package liquibase.datatype.core; - -import liquibase.change.core.LoadDataChange; -import liquibase.database.Database; -import liquibase.database.core.*; -import liquibase.datatype.DataTypeInfo; -import liquibase.datatype.DatabaseDataType; -import liquibase.datatype.LiquibaseDataType; -import liquibase.exception.UnexpectedLiquibaseException; -import liquibase.statement.DatabaseFunction; -import liquibase.util.StringUtil; - -import java.util.Locale; -import java.util.regex.Pattern; - -@DataTypeInfo(name = "boolean", aliases = {"java.sql.Types.BOOLEAN", "java.lang.Boolean", "bit", "bool"}, minParameters = 0, maxParameters = 0, priority = LiquibaseDataType.PRIORITY_DEFAULT) -public class BooleanType extends LiquibaseDataType { - - @Override - public DatabaseDataType toDatabaseDataType(Database database) { - String originalDefinition = StringUtil.trimToEmpty(getRawDefinition()); - if ((database instanceof Firebird3Database)) { - return new DatabaseDataType("BOOLEAN"); - } - - if ((database instanceof Db2zDatabase) || (database instanceof FirebirdDatabase)) { - return new DatabaseDataType("SMALLINT"); - } else if (database instanceof MSSQLDatabase) { - return new DatabaseDataType(database.escapeDataTypeName("bit")); - } else if (database instanceof MySQLDatabase) { - if (originalDefinition.toLowerCase(Locale.US).startsWith("bit")) { - return new DatabaseDataType("BIT", getParameters()); - } - return new DatabaseDataType("BIT", 1); - } else if (database instanceof OracleDatabase) { - return new DatabaseDataType("NUMBER", 1); - } else if ((database instanceof SybaseASADatabase) || (database instanceof SybaseDatabase)) { - return new DatabaseDataType("BIT"); - } else if (database instanceof DerbyDatabase) { - if (((DerbyDatabase) database).supportsBooleanDataType()) { - return new DatabaseDataType("BOOLEAN"); - } else { - return new DatabaseDataType("SMALLINT"); - } - } else if (database instanceof DB2Database) { - if (((DB2Database) database).supportsBooleanDataType()) - return new DatabaseDataType("BOOLEAN"); - else - return new DatabaseDataType("SMALLINT"); - } else if (database instanceof HsqlDatabase) { - return new DatabaseDataType("BOOLEAN"); - } else if (database instanceof PostgresDatabase) { - if (originalDefinition.toLowerCase(Locale.US).startsWith("bit")) { - return new DatabaseDataType("BIT", getParameters()); - } - } else if (database instanceof DmDatabase) { // dhb52: DM Support - return new DatabaseDataType("bit"); - } - - return super.toDatabaseDataType(database); - } - - @Override - public String objectToSql(Object value, Database database) { - if ((value == null) || "null".equals(value.toString().toLowerCase(Locale.US))) { - return null; - } - - String returnValue; - if (value instanceof String) { - value = ((String) value).replaceAll("'", ""); - 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))) { - returnValue = this.getTrueBooleanValue(database); - } else if ("false".equals(((String) value).toLowerCase(Locale.US)) || "0".equals(value) || "b'0'".equals( - ((String) value).toLowerCase(Locale.US)) || "f".equals(((String) value).toLowerCase(Locale.US)) || ((String) value).toLowerCase(Locale.US).equals(this.getFalseBooleanValue(database).toLowerCase(Locale.US))) { - returnValue = this.getFalseBooleanValue(database); - } else if (database instanceof PostgresDatabase && Pattern.matches("b?([01])\\1*(::bit|::\"bit\")?", (String) value)) { - returnValue = "b'" - + value.toString() - .replace("b", "") - .replace("\"", "") - .replace("::it", "") - + "'::\"bit\""; - } else { - throw new UnexpectedLiquibaseException("Unknown boolean value: " + value); - } - } else if (value instanceof Long) { - if (Long.valueOf(1).equals(value)) { - returnValue = this.getTrueBooleanValue(database); - } else { - returnValue = this.getFalseBooleanValue(database); - } - } else if (value instanceof Number) { - if (value.equals(1) || "1".equals(value.toString()) || "1.0".equals(value.toString())) { - returnValue = this.getTrueBooleanValue(database); - } else { - returnValue = this.getFalseBooleanValue(database); - } - } else if (value instanceof DatabaseFunction) { - return value.toString(); - } else if (value instanceof Boolean) { - if (((Boolean) value)) { - returnValue = this.getTrueBooleanValue(database); - } else { - returnValue = this.getFalseBooleanValue(database); - } - } else { - throw new UnexpectedLiquibaseException("Cannot convert type " + value.getClass() + " to a boolean value"); - } - - return returnValue; - } - - protected boolean isNumericBoolean(Database database) { - if (database instanceof Firebird3Database) { - return false; - } - if (database instanceof DerbyDatabase) { - return !((DerbyDatabase) database).supportsBooleanDataType(); - } else if (database instanceof DB2Database) { - return !((DB2Database) database).supportsBooleanDataType(); - } - return (database instanceof Db2zDatabase) - || (database instanceof FirebirdDatabase) - || (database instanceof MSSQLDatabase) - || (database instanceof MySQLDatabase) - || (database instanceof OracleDatabase) - || (database instanceof SQLiteDatabase) - || (database instanceof SybaseASADatabase) - || (database instanceof SybaseDatabase) - || (database instanceof DmDatabase); // dhb52: DM Support - } - - /** - * The database-specific value to use for "false" "boolean" columns. - */ - public String getFalseBooleanValue(Database database) { - if (isNumericBoolean(database)) { - return "0"; - } - if (database instanceof InformixDatabase) { - return "'f'"; - } - return "FALSE"; - } - - /** - * The database-specific value to use for "true" "boolean" columns. - */ - public String getTrueBooleanValue(Database database) { - if (isNumericBoolean(database)) { - return "1"; - } - if (database instanceof InformixDatabase) { - return "'t'"; - } - return "TRUE"; - } - - @Override - public LoadDataChange.LOAD_DATA_TYPE getLoadTypeName() { - return LoadDataChange.LOAD_DATA_TYPE.BOOLEAN; - } - -} diff --git a/sql/db2/flowable-patch/src/main/java/org/flowable/common/engine/impl/AbstractEngineConfiguration.java b/sql/db2/flowable-patch/src/main/java/org/flowable/common/engine/impl/AbstractEngineConfiguration.java deleted file mode 100644 index 33c52d551..000000000 --- a/sql/db2/flowable-patch/src/main/java/org/flowable/common/engine/impl/AbstractEngineConfiguration.java +++ /dev/null @@ -1,2068 +0,0 @@ -/* Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.flowable.common.engine.impl; - -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.time.Duration; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.ServiceLoader; -import java.util.Set; - -import javax.naming.InitialContext; -import javax.sql.DataSource; - -import org.apache.commons.lang3.StringUtils; -import org.apache.ibatis.builder.xml.XMLConfigBuilder; -import org.apache.ibatis.builder.xml.XMLMapperBuilder; -import org.apache.ibatis.datasource.pooled.PooledDataSource; -import org.apache.ibatis.mapping.Environment; -import org.apache.ibatis.plugin.Interceptor; -import org.apache.ibatis.session.Configuration; -import org.apache.ibatis.session.SqlSessionFactory; -import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory; -import org.apache.ibatis.transaction.TransactionFactory; -import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; -import org.apache.ibatis.transaction.managed.ManagedTransactionFactory; -import org.apache.ibatis.type.ArrayTypeHandler; -import org.apache.ibatis.type.BigDecimalTypeHandler; -import org.apache.ibatis.type.BlobInputStreamTypeHandler; -import org.apache.ibatis.type.BlobTypeHandler; -import org.apache.ibatis.type.BooleanTypeHandler; -import org.apache.ibatis.type.ByteTypeHandler; -import org.apache.ibatis.type.ClobTypeHandler; -import org.apache.ibatis.type.DateOnlyTypeHandler; -import org.apache.ibatis.type.DateTypeHandler; -import org.apache.ibatis.type.DoubleTypeHandler; -import org.apache.ibatis.type.FloatTypeHandler; -import org.apache.ibatis.type.IntegerTypeHandler; -import org.apache.ibatis.type.JdbcType; -import org.apache.ibatis.type.LongTypeHandler; -import org.apache.ibatis.type.NClobTypeHandler; -import org.apache.ibatis.type.NStringTypeHandler; -import org.apache.ibatis.type.ShortTypeHandler; -import org.apache.ibatis.type.SqlxmlTypeHandler; -import org.apache.ibatis.type.StringTypeHandler; -import org.apache.ibatis.type.TimeOnlyTypeHandler; -import org.apache.ibatis.type.TypeHandlerRegistry; -import org.flowable.common.engine.api.FlowableException; -import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType; -import org.flowable.common.engine.api.delegate.event.FlowableEventDispatcher; -import org.flowable.common.engine.api.delegate.event.FlowableEventListener; -import org.flowable.common.engine.api.engine.EngineLifecycleListener; -import org.flowable.common.engine.impl.agenda.AgendaOperationRunner; -import org.flowable.common.engine.impl.cfg.CommandExecutorImpl; -import org.flowable.common.engine.impl.cfg.IdGenerator; -import org.flowable.common.engine.impl.cfg.TransactionContextFactory; -import org.flowable.common.engine.impl.cfg.standalone.StandaloneMybatisTransactionContextFactory; -import org.flowable.common.engine.impl.db.CommonDbSchemaManager; -import org.flowable.common.engine.impl.db.DbSqlSessionFactory; -import org.flowable.common.engine.impl.db.LogSqlExecutionTimePlugin; -import org.flowable.common.engine.impl.db.MybatisTypeAliasConfigurator; -import org.flowable.common.engine.impl.db.MybatisTypeHandlerConfigurator; -import org.flowable.common.engine.impl.db.SchemaManager; -import org.flowable.common.engine.impl.event.EventDispatchAction; -import org.flowable.common.engine.impl.event.FlowableEventDispatcherImpl; -import org.flowable.common.engine.impl.interceptor.Command; -import org.flowable.common.engine.impl.interceptor.CommandConfig; -import org.flowable.common.engine.impl.interceptor.CommandContextFactory; -import org.flowable.common.engine.impl.interceptor.CommandContextInterceptor; -import org.flowable.common.engine.impl.interceptor.CommandExecutor; -import org.flowable.common.engine.impl.interceptor.CommandInterceptor; -import org.flowable.common.engine.impl.interceptor.CrDbRetryInterceptor; -import org.flowable.common.engine.impl.interceptor.DefaultCommandInvoker; -import org.flowable.common.engine.impl.interceptor.LogInterceptor; -import org.flowable.common.engine.impl.interceptor.SessionFactory; -import org.flowable.common.engine.impl.interceptor.TransactionContextInterceptor; -import org.flowable.common.engine.impl.lock.LockManager; -import org.flowable.common.engine.impl.lock.LockManagerImpl; -import org.flowable.common.engine.impl.logging.LoggingListener; -import org.flowable.common.engine.impl.logging.LoggingSession; -import org.flowable.common.engine.impl.logging.LoggingSessionFactory; -import org.flowable.common.engine.impl.persistence.GenericManagerFactory; -import org.flowable.common.engine.impl.persistence.StrongUuidGenerator; -import org.flowable.common.engine.impl.persistence.cache.EntityCache; -import org.flowable.common.engine.impl.persistence.cache.EntityCacheImpl; -import org.flowable.common.engine.impl.persistence.entity.ByteArrayEntityManager; -import org.flowable.common.engine.impl.persistence.entity.ByteArrayEntityManagerImpl; -import org.flowable.common.engine.impl.persistence.entity.Entity; -import org.flowable.common.engine.impl.persistence.entity.PropertyEntityManager; -import org.flowable.common.engine.impl.persistence.entity.PropertyEntityManagerImpl; -import org.flowable.common.engine.impl.persistence.entity.TableDataManager; -import org.flowable.common.engine.impl.persistence.entity.TableDataManagerImpl; -import org.flowable.common.engine.impl.persistence.entity.data.ByteArrayDataManager; -import org.flowable.common.engine.impl.persistence.entity.data.PropertyDataManager; -import org.flowable.common.engine.impl.persistence.entity.data.impl.MybatisByteArrayDataManager; -import org.flowable.common.engine.impl.persistence.entity.data.impl.MybatisPropertyDataManager; -import org.flowable.common.engine.impl.runtime.Clock; -import org.flowable.common.engine.impl.service.CommonEngineServiceImpl; -import org.flowable.common.engine.impl.util.DefaultClockImpl; -import org.flowable.common.engine.impl.util.IoUtil; -import org.flowable.common.engine.impl.util.ReflectUtil; -import org.flowable.eventregistry.api.EventRegistryEventConsumer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; - -public abstract class AbstractEngineConfiguration { - - protected final Logger logger = LoggerFactory.getLogger(getClass()); - - /** The tenant id indicating 'no tenant' */ - public static final String NO_TENANT_ID = ""; - - /** - * 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. - */ - public static final String DB_SCHEMA_UPDATE_FALSE = "false"; - public static final String DB_SCHEMA_UPDATE_CREATE = "create"; - public static final String DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop"; - - /** - * Creates the schema when the form engine is being created and drops the schema when the form engine is being closed. - */ - public static final String DB_SCHEMA_UPDATE_DROP_CREATE = "drop-create"; - - /** - * Upon building of the process engine, a check is performed and an update of the schema is performed if it is necessary. - */ - public static final String DB_SCHEMA_UPDATE_TRUE = "true"; - - protected boolean forceCloseMybatisConnectionPool = true; - - protected String databaseType; - protected String jdbcDriver = "org.h2.Driver"; - protected String jdbcUrl = "jdbc:h2:tcp://localhost/~/flowable"; - protected String jdbcUsername = "sa"; - protected String jdbcPassword = ""; - protected String dataSourceJndiName; - protected int jdbcMaxActiveConnections = 16; - protected int jdbcMaxIdleConnections = 8; - protected int jdbcMaxCheckoutTime; - protected int jdbcMaxWaitTime; - protected boolean jdbcPingEnabled; - protected String jdbcPingQuery; - protected int jdbcPingConnectionNotUsedFor; - protected int jdbcDefaultTransactionIsolationLevel; - protected DataSource dataSource; - protected SchemaManager commonSchemaManager; - protected SchemaManager schemaManager; - protected Command schemaManagementCmd; - - protected String databaseSchemaUpdate = DB_SCHEMA_UPDATE_FALSE; - - /** - * Whether to use a lock when performing the database schema create or update operations. - */ - protected boolean useLockForDatabaseSchemaUpdate = false; - - protected String xmlEncoding = "UTF-8"; - - // COMMAND EXECUTORS /////////////////////////////////////////////// - - protected CommandExecutor commandExecutor; - protected Collection defaultCommandInterceptors; - protected CommandConfig defaultCommandConfig; - protected CommandConfig schemaCommandConfig; - protected CommandContextFactory commandContextFactory; - protected CommandInterceptor commandInvoker; - - protected AgendaOperationRunner agendaOperationRunner = (commandContext, runnable) -> runnable.run(); - - protected List customPreCommandInterceptors; - protected List customPostCommandInterceptors; - protected List commandInterceptors; - - protected Map engineConfigurations = new HashMap<>(); - protected Map serviceConfigurations = new HashMap<>(); - - protected ClassLoader classLoader; - /** - * Either use Class.forName or ClassLoader.loadClass for class loading. See http://forums.activiti.org/content/reflectutilloadclass-and-custom- classloader - */ - protected boolean useClassForNameClassLoading = true; - - protected List engineLifecycleListeners; - - // Event Registry ////////////////////////////////////////////////// - protected Map eventRegistryEventConsumers = new HashMap<>(); - - // MYBATIS SQL SESSION FACTORY ///////////////////////////////////// - - protected boolean isDbHistoryUsed = true; - protected DbSqlSessionFactory dbSqlSessionFactory; - protected SqlSessionFactory sqlSessionFactory; - protected TransactionFactory transactionFactory; - protected TransactionContextFactory transactionContextFactory; - - /** - * If set to true, enables bulk insert (grouping sql inserts together). Default true. - * For some databases (eg DB2+z/OS) needs to be set to false. - */ - protected boolean isBulkInsertEnabled = true; - - /** - * 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 - * 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. - *

- * By default: 100 (55 for mssql server as it has a hard limit of 2000 parameters in a statement) - */ - protected int maxNrOfStatementsInBulkInsert = 100; - - public int DEFAULT_MAX_NR_OF_STATEMENTS_BULK_INSERT_SQL_SERVER = 55; // currently Execution has most params (35). 2000 / 35 = 57. - - protected String mybatisMappingFile; - protected Set> customMybatisMappers; - protected Set customMybatisXMLMappers; - protected List customMybatisInterceptors; - - protected Set dependentEngineMyBatisXmlMappers; - protected List dependentEngineMybatisTypeAliasConfigs; - protected List dependentEngineMybatisTypeHandlerConfigs; - - // SESSION FACTORIES /////////////////////////////////////////////// - protected List customSessionFactories; - protected Map, SessionFactory> sessionFactories; - - protected boolean enableEventDispatcher = true; - protected FlowableEventDispatcher eventDispatcher; - protected List eventListeners; - protected Map> typedEventListeners; - protected List additionalEventDispatchActions; - - protected LoggingListener loggingListener; - - protected boolean transactionsExternallyManaged; - - /** - * 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. - * - * If true (default), the {@link AbstractEngineConfiguration#getDatabaseSchemaUpdate()} value will be used to determine what needs to happen wrt the database schema. - * - * 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 - * correct. The {@link AbstractEngineConfiguration#getDatabaseSchemaUpdate()} value will not be used. - */ - protected boolean usingRelationalDatabase = true; - - /** - * 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. - * Setting {@link #usingRelationalDatabase} to true will automatically imply using a schema. - */ - protected boolean usingSchemaMgmt = true; - - /** - * 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 - * in a table named 'PRE1.ACT_RU_EXECUTION_'. - * - *

- * NOTE: the prefix is not respected by automatic database schema management. If you use {@link AbstractEngineConfiguration#DB_SCHEMA_UPDATE_CREATE_DROP} or - * {@link AbstractEngineConfiguration#DB_SCHEMA_UPDATE_TRUE}, Flowable will create the database tables using the default names, regardless of the prefix configured here. - */ - protected String databaseTablePrefix = ""; - - /** - * Escape character for doing wildcard searches. - * - * 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 '\'; - */ - protected String databaseWildcardEscapeCharacter; - - /** - * database catalog to use - */ - protected String databaseCatalog = ""; - - /** - * 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, - * https://jira.codehaus.org/browse/ACT-1062 - */ - protected String databaseSchema; - - /** - * 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 - * 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. - */ - protected boolean tablePrefixIsSchema; - - /** - * Set to true if the latest version of a definition should be retrieved, ignoring a possible parent deployment id value - */ - protected boolean alwaysLookupLatestDefinitionVersion; - - /** - * Set to true if by default lookups should fallback to the default tenant (an empty string by default or a defined tenant value) - */ - protected boolean fallbackToDefaultTenant; - - /** - * Default tenant provider that is executed when looking up definitions, in case the global or local fallback to default tenant value is true - */ - protected DefaultTenantProvider defaultTenantProvider = (tenantId, scope, scopeKey) -> NO_TENANT_ID; - - /** - * Enables the MyBatis plugin that logs the execution time of sql statements. - */ - protected boolean enableLogSqlExecutionTime; - - protected Properties databaseTypeMappings = getDefaultDatabaseTypeMappings(); - - /** - * Duration between the checks when acquiring a lock. - */ - protected Duration lockPollRate = Duration.ofSeconds(10); - - /** - * Duration to wait for the DB Schema lock before giving up. - */ - protected Duration schemaLockWaitTime = Duration.ofMinutes(5); - - // DATA MANAGERS ////////////////////////////////////////////////////////////////// - - protected PropertyDataManager propertyDataManager; - protected ByteArrayDataManager byteArrayDataManager; - protected TableDataManager tableDataManager; - - // ENTITY MANAGERS //////////////////////////////////////////////////////////////// - - protected PropertyEntityManager propertyEntityManager; - protected ByteArrayEntityManager byteArrayEntityManager; - - protected List customPreDeployers; - protected List customPostDeployers; - protected List deployers; - - // CONFIGURATORS //////////////////////////////////////////////////////////// - - protected boolean enableConfiguratorServiceLoader = true; // Enabled by default. In certain environments this should be set to false (eg osgi) - protected List configurators; // The injected configurators - protected List allConfigurators; // Including auto-discovered configurators - protected EngineConfigurator idmEngineConfigurator; - protected EngineConfigurator eventRegistryConfigurator; - - public static final String PRODUCT_NAME_POSTGRES = "PostgreSQL"; - public static final String PRODUCT_NAME_CRDB = "CockroachDB"; - - public static final String DATABASE_TYPE_H2 = "h2"; - public static final String DATABASE_TYPE_HSQL = "hsql"; - public static final String DATABASE_TYPE_MYSQL = "mysql"; - public static final String DATABASE_TYPE_ORACLE = "oracle"; - public static final String DATABASE_TYPE_POSTGRES = "postgres"; - public static final String DATABASE_TYPE_MSSQL = "mssql"; - public static final String DATABASE_TYPE_DB2 = "db2"; - public static final String DATABASE_TYPE_COCKROACHDB = "cockroachdb"; - - public static Properties getDefaultDatabaseTypeMappings() { - Properties databaseTypeMappings = new Properties(); - databaseTypeMappings.setProperty("H2", DATABASE_TYPE_H2); - databaseTypeMappings.setProperty("HSQL Database Engine", DATABASE_TYPE_HSQL); - databaseTypeMappings.setProperty("MySQL", DATABASE_TYPE_MYSQL); - databaseTypeMappings.setProperty("MariaDB", DATABASE_TYPE_MYSQL); - databaseTypeMappings.setProperty("Oracle", DATABASE_TYPE_ORACLE); - databaseTypeMappings.setProperty(PRODUCT_NAME_POSTGRES, DATABASE_TYPE_POSTGRES); - databaseTypeMappings.setProperty("Microsoft SQL Server", DATABASE_TYPE_MSSQL); - databaseTypeMappings.setProperty(DATABASE_TYPE_DB2, DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2/NT", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2/NT64", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2 UDP", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2/LINUX", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2/LINUX390", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2/LINUXX8664", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2/LINUXZ64", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2/LINUXPPC64", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2/LINUXPPC64LE", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2/400 SQL", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2/6000", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2 UDB iSeries", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2/AIX64", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2/HPUX", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2/HP64", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2/SUN", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2/SUN64", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2/PTX", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2/2", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty("DB2 UDB AS400", DATABASE_TYPE_DB2); - databaseTypeMappings.setProperty(PRODUCT_NAME_CRDB, DATABASE_TYPE_COCKROACHDB); - databaseTypeMappings.setProperty("DM DBMS", DATABASE_TYPE_ORACLE); // dhb52: DM support - return databaseTypeMappings; - } - - protected Map beans; - - protected IdGenerator idGenerator; - protected boolean usePrefixId; - - protected Clock clock; - protected ObjectMapper objectMapper; - - // Variables - - public static final int DEFAULT_GENERIC_MAX_LENGTH_STRING = 4000; - public static final int DEFAULT_ORACLE_MAX_LENGTH_STRING = 2000; - - /** - * Define a max length for storing String variable types in the database. Mainly used for the Oracle NVARCHAR2 limit of 2000 characters - */ - protected int maxLengthStringVariableType = -1; - - protected void initEngineConfigurations() { - addEngineConfiguration(getEngineCfgKey(), getEngineScopeType(), this); - } - - // DataSource - // /////////////////////////////////////////////////////////////// - - protected void initDataSource() { - if (dataSource == null) { - if (dataSourceJndiName != null) { - try { - dataSource = (DataSource) new InitialContext().lookup(dataSourceJndiName); - } catch (Exception e) { - throw new FlowableException("couldn't lookup datasource from " + dataSourceJndiName + ": " + e.getMessage(), e); - } - - } else if (jdbcUrl != null) { - if ((jdbcDriver == null) || (jdbcUsername == null)) { - throw new FlowableException("DataSource or JDBC properties have to be specified in a process engine configuration"); - } - - logger.debug("initializing datasource to db: {}", jdbcUrl); - - if (logger.isInfoEnabled()) { - logger.info("Configuring Datasource with following properties (omitted password for security)"); - logger.info("datasource driver : {}", jdbcDriver); - logger.info("datasource url : {}", jdbcUrl); - logger.info("datasource user name : {}", jdbcUsername); - } - - PooledDataSource pooledDataSource = new PooledDataSource(this.getClass().getClassLoader(), jdbcDriver, jdbcUrl, jdbcUsername, jdbcPassword); - - if (jdbcMaxActiveConnections > 0) { - pooledDataSource.setPoolMaximumActiveConnections(jdbcMaxActiveConnections); - } - if (jdbcMaxIdleConnections > 0) { - pooledDataSource.setPoolMaximumIdleConnections(jdbcMaxIdleConnections); - } - if (jdbcMaxCheckoutTime > 0) { - pooledDataSource.setPoolMaximumCheckoutTime(jdbcMaxCheckoutTime); - } - if (jdbcMaxWaitTime > 0) { - pooledDataSource.setPoolTimeToWait(jdbcMaxWaitTime); - } - if (jdbcPingEnabled) { - pooledDataSource.setPoolPingEnabled(true); - if (jdbcPingQuery != null) { - pooledDataSource.setPoolPingQuery(jdbcPingQuery); - } - pooledDataSource.setPoolPingConnectionsNotUsedFor(jdbcPingConnectionNotUsedFor); - } - if (jdbcDefaultTransactionIsolationLevel > 0) { - pooledDataSource.setDefaultTransactionIsolationLevel(jdbcDefaultTransactionIsolationLevel); - } - dataSource = pooledDataSource; - } - } - - if (databaseType == null) { - initDatabaseType(); - } - } - - public void initDatabaseType() { - Connection connection = null; - try { - connection = dataSource.getConnection(); - DatabaseMetaData databaseMetaData = connection.getMetaData(); - String databaseProductName = databaseMetaData.getDatabaseProductName(); - logger.debug("database product name: '{}'", databaseProductName); - - // CRDB does not expose the version through the jdbc driver, so we need to fetch it through version(). - if (PRODUCT_NAME_POSTGRES.equalsIgnoreCase(databaseProductName)) { - try (PreparedStatement preparedStatement = connection.prepareStatement("select version() as version;"); - ResultSet resultSet = preparedStatement.executeQuery()) { - String version = null; - if (resultSet.next()) { - version = resultSet.getString("version"); - } - - if (StringUtils.isNotEmpty(version) && version.toLowerCase().startsWith(PRODUCT_NAME_CRDB.toLowerCase())) { - databaseProductName = PRODUCT_NAME_CRDB; - logger.info("CockroachDB version '{}' detected", version); - } - } - } - - databaseType = databaseTypeMappings.getProperty(databaseProductName); - if (databaseType == null) { - throw new FlowableException("couldn't deduct database type from database product name '" + databaseProductName + "'"); - } - logger.debug("using database type: {}", databaseType); - - } catch (SQLException e) { - throw new RuntimeException("Exception while initializing Database connection", e); - } finally { - try { - if (connection != null) { - connection.close(); - } - } catch (SQLException e) { - logger.error("Exception while closing the Database connection", e); - } - } - - // Special care for MSSQL, as it has a hard limit of 2000 params per statement (incl bulk statement). - // Especially with executions, with 100 as default, this limit is passed. - if (DATABASE_TYPE_MSSQL.equals(databaseType)) { - maxNrOfStatementsInBulkInsert = DEFAULT_MAX_NR_OF_STATEMENTS_BULK_INSERT_SQL_SERVER; - } - } - - public void initSchemaManager() { - if (this.commonSchemaManager == null) { - this.commonSchemaManager = new CommonDbSchemaManager(); - } - } - - // session factories //////////////////////////////////////////////////////// - - public void addSessionFactory(SessionFactory sessionFactory) { - sessionFactories.put(sessionFactory.getSessionType(), sessionFactory); - } - - public void initCommandContextFactory() { - if (commandContextFactory == null) { - commandContextFactory = new CommandContextFactory(); - } - } - - public void initTransactionContextFactory() { - if (transactionContextFactory == null) { - transactionContextFactory = new StandaloneMybatisTransactionContextFactory(); - } - } - - public void initCommandExecutors() { - initDefaultCommandConfig(); - initSchemaCommandConfig(); - initCommandInvoker(); - initCommandInterceptors(); - initCommandExecutor(); - } - - - public void initDefaultCommandConfig() { - if (defaultCommandConfig == null) { - defaultCommandConfig = new CommandConfig(); - } - } - - public void initSchemaCommandConfig() { - if (schemaCommandConfig == null) { - schemaCommandConfig = new CommandConfig(); - } - } - - public void initCommandInvoker() { - if (commandInvoker == null) { - commandInvoker = new DefaultCommandInvoker(); - } - } - - public void initCommandInterceptors() { - if (commandInterceptors == null) { - commandInterceptors = new ArrayList<>(); - if (customPreCommandInterceptors != null) { - commandInterceptors.addAll(customPreCommandInterceptors); - } - commandInterceptors.addAll(getDefaultCommandInterceptors()); - if (customPostCommandInterceptors != null) { - commandInterceptors.addAll(customPostCommandInterceptors); - } - commandInterceptors.add(commandInvoker); - } - } - - public Collection getDefaultCommandInterceptors() { - if (defaultCommandInterceptors == null) { - List interceptors = new ArrayList<>(); - interceptors.add(new LogInterceptor()); - - if (DATABASE_TYPE_COCKROACHDB.equals(databaseType)) { - interceptors.add(new CrDbRetryInterceptor()); - } - - CommandInterceptor transactionInterceptor = createTransactionInterceptor(); - if (transactionInterceptor != null) { - interceptors.add(transactionInterceptor); - } - - if (commandContextFactory != null) { - String engineCfgKey = getEngineCfgKey(); - CommandContextInterceptor commandContextInterceptor = new CommandContextInterceptor(commandContextFactory, - classLoader, useClassForNameClassLoading, clock, objectMapper); - engineConfigurations.put(engineCfgKey, this); - commandContextInterceptor.setEngineCfgKey(engineCfgKey); - commandContextInterceptor.setEngineConfigurations(engineConfigurations); - interceptors.add(commandContextInterceptor); - } - - if (transactionContextFactory != null) { - interceptors.add(new TransactionContextInterceptor(transactionContextFactory)); - } - - List additionalCommandInterceptors = getAdditionalDefaultCommandInterceptors(); - if (additionalCommandInterceptors != null) { - interceptors.addAll(additionalCommandInterceptors); - } - - defaultCommandInterceptors = interceptors; - } - return defaultCommandInterceptors; - } - - public abstract String getEngineCfgKey(); - - public abstract String getEngineScopeType(); - - public List getAdditionalDefaultCommandInterceptors() { - return null; - } - - public void initCommandExecutor() { - if (commandExecutor == null) { - CommandInterceptor first = initInterceptorChain(commandInterceptors); - commandExecutor = new CommandExecutorImpl(getDefaultCommandConfig(), first); - } - } - - public CommandInterceptor initInterceptorChain(List chain) { - if (chain == null || chain.isEmpty()) { - throw new FlowableException("invalid command interceptor chain configuration: " + chain); - } - for (int i = 0; i < chain.size() - 1; i++) { - chain.get(i).setNext(chain.get(i + 1)); - } - return chain.get(0); - } - - public abstract CommandInterceptor createTransactionInterceptor(); - - - public void initBeans() { - if (beans == null) { - beans = new HashMap<>(); - } - } - - // id generator - // ///////////////////////////////////////////////////////////// - - public void initIdGenerator() { - if (idGenerator == null) { - idGenerator = new StrongUuidGenerator(); - } - } - - public void initObjectMapper() { - if (objectMapper == null) { - objectMapper = new ObjectMapper(); - objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); - } - } - - public void initClock() { - if (clock == null) { - clock = new DefaultClockImpl(); - } - } - - // Data managers /////////////////////////////////////////////////////////// - - public void initDataManagers() { - if (propertyDataManager == null) { - propertyDataManager = new MybatisPropertyDataManager(idGenerator); - } - - if (byteArrayDataManager == null) { - byteArrayDataManager = new MybatisByteArrayDataManager(idGenerator); - } - } - - // Entity managers ////////////////////////////////////////////////////////// - - public void initEntityManagers() { - if (propertyEntityManager == null) { - propertyEntityManager = new PropertyEntityManagerImpl(this, propertyDataManager); - } - - if (byteArrayEntityManager == null) { - byteArrayEntityManager = new ByteArrayEntityManagerImpl(byteArrayDataManager, getEngineCfgKey(), this::getEventDispatcher); - } - - if (tableDataManager == null) { - tableDataManager = new TableDataManagerImpl(this); - } - } - - // services - // ///////////////////////////////////////////////////////////////// - - protected void initService(Object service) { - if (service instanceof CommonEngineServiceImpl) { - ((CommonEngineServiceImpl) service).setCommandExecutor(commandExecutor); - } - } - - // myBatis SqlSessionFactory - // //////////////////////////////////////////////// - - public void initSessionFactories() { - if (sessionFactories == null) { - sessionFactories = new HashMap<>(); - - if (usingRelationalDatabase) { - initDbSqlSessionFactory(); - } - - addSessionFactory(new GenericManagerFactory(EntityCache.class, EntityCacheImpl.class)); - - if (isLoggingSessionEnabled()) { - if (!sessionFactories.containsKey(LoggingSession.class)) { - LoggingSessionFactory loggingSessionFactory = new LoggingSessionFactory(); - loggingSessionFactory.setLoggingListener(loggingListener); - loggingSessionFactory.setObjectMapper(objectMapper); - sessionFactories.put(LoggingSession.class, loggingSessionFactory); - } - } - - commandContextFactory.setSessionFactories(sessionFactories); - - } else { - if (usingRelationalDatabase) { - initDbSqlSessionFactoryEntitySettings(); - } - } - - if (customSessionFactories != null) { - for (SessionFactory sessionFactory : customSessionFactories) { - addSessionFactory(sessionFactory); - } - } - } - - public void initDbSqlSessionFactory() { - if (dbSqlSessionFactory == null) { - dbSqlSessionFactory = createDbSqlSessionFactory(); - } - dbSqlSessionFactory.setDatabaseType(databaseType); - dbSqlSessionFactory.setSqlSessionFactory(sqlSessionFactory); - dbSqlSessionFactory.setDbHistoryUsed(isDbHistoryUsed); - dbSqlSessionFactory.setDatabaseTablePrefix(databaseTablePrefix); - dbSqlSessionFactory.setTablePrefixIsSchema(tablePrefixIsSchema); - dbSqlSessionFactory.setDatabaseCatalog(databaseCatalog); - dbSqlSessionFactory.setDatabaseSchema(databaseSchema); - dbSqlSessionFactory.setMaxNrOfStatementsInBulkInsert(maxNrOfStatementsInBulkInsert); - - initDbSqlSessionFactoryEntitySettings(); - - addSessionFactory(dbSqlSessionFactory); - } - - public DbSqlSessionFactory createDbSqlSessionFactory() { - return new DbSqlSessionFactory(usePrefixId); - } - - protected abstract void initDbSqlSessionFactoryEntitySettings(); - - protected void defaultInitDbSqlSessionFactoryEntitySettings(List> insertOrder, List> deleteOrder) { - if (insertOrder != null) { - for (Class clazz : insertOrder) { - dbSqlSessionFactory.getInsertionOrder().add(clazz); - - if (isBulkInsertEnabled) { - dbSqlSessionFactory.getBulkInserteableEntityClasses().add(clazz); - } - } - } - - if (deleteOrder != null) { - for (Class clazz : deleteOrder) { - dbSqlSessionFactory.getDeletionOrder().add(clazz); - } - } - } - - public void initTransactionFactory() { - if (transactionFactory == null) { - if (transactionsExternallyManaged) { - transactionFactory = new ManagedTransactionFactory(); - Properties properties = new Properties(); - properties.put("closeConnection", "false"); - this.transactionFactory.setProperties(properties); - } else { - transactionFactory = new JdbcTransactionFactory(); - } - } - } - - public void initSqlSessionFactory() { - if (sqlSessionFactory == null) { - InputStream inputStream = null; - try { - inputStream = getMyBatisXmlConfigurationStream(); - - Environment environment = new Environment("default", transactionFactory, dataSource); - Reader reader = new InputStreamReader(inputStream); - Properties properties = new Properties(); - properties.put("prefix", databaseTablePrefix); - - String wildcardEscapeClause = ""; - if ((databaseWildcardEscapeCharacter != null) && (databaseWildcardEscapeCharacter.length() != 0)) { - wildcardEscapeClause = " escape '" + databaseWildcardEscapeCharacter + "'"; - } - properties.put("wildcardEscapeClause", wildcardEscapeClause); - - // set default properties - properties.put("limitBefore", ""); - properties.put("limitAfter", ""); - properties.put("limitBetween", ""); - properties.put("limitBeforeNativeQuery", ""); - properties.put("limitAfterNativeQuery", ""); - properties.put("blobType", "BLOB"); - properties.put("boolValue", "TRUE"); - - if (databaseType != null) { - properties.load(getResourceAsStream(pathToEngineDbProperties())); - } - - Configuration configuration = initMybatisConfiguration(environment, reader, properties); - sqlSessionFactory = new DefaultSqlSessionFactory(configuration); - - } catch (Exception e) { - throw new FlowableException("Error while building ibatis SqlSessionFactory: " + e.getMessage(), e); - } finally { - IoUtil.closeSilently(inputStream); - } - } else { - // This is needed when the SQL Session Factory is created by another engine. - // When custom XML Mappers are registered with this engine they need to be loaded in the configuration as well - applyCustomMybatisCustomizations(sqlSessionFactory.getConfiguration()); - } - } - - public String pathToEngineDbProperties() { - return "org/flowable/common/db/properties/" + databaseType + ".properties"; - } - - public Configuration initMybatisConfiguration(Environment environment, Reader reader, Properties properties) { - XMLConfigBuilder parser = new XMLConfigBuilder(reader, "", properties); - Configuration configuration = parser.getConfiguration(); - - if (databaseType != null) { - configuration.setDatabaseId(databaseType); - } - - configuration.setEnvironment(environment); - - initMybatisTypeHandlers(configuration); - initCustomMybatisInterceptors(configuration); - if (isEnableLogSqlExecutionTime()) { - initMyBatisLogSqlExecutionTimePlugin(configuration); - } - - configuration = parseMybatisConfiguration(parser); - return configuration; - } - - public void initCustomMybatisMappers(Configuration configuration) { - if (getCustomMybatisMappers() != null) { - for (Class clazz : getCustomMybatisMappers()) { - if (!configuration.hasMapper(clazz)) { - configuration.addMapper(clazz); - } - } - } - } - - public void initMybatisTypeHandlers(Configuration configuration) { - // When mapping into Map there is currently a problem with MyBatis. - // It will return objects which are driver specific. - // Therefore we are registering the mappings between Object.class and the specific jdbc type here. - // see https://github.com/mybatis/mybatis-3/issues/2216 for more info - TypeHandlerRegistry handlerRegistry = configuration.getTypeHandlerRegistry(); - - handlerRegistry.register(Object.class, JdbcType.BOOLEAN, new BooleanTypeHandler()); - handlerRegistry.register(Object.class, JdbcType.BIT, new BooleanTypeHandler()); - - handlerRegistry.register(Object.class, JdbcType.TINYINT, new ByteTypeHandler()); - - handlerRegistry.register(Object.class, JdbcType.SMALLINT, new ShortTypeHandler()); - - handlerRegistry.register(Object.class, JdbcType.INTEGER, new IntegerTypeHandler()); - - handlerRegistry.register(Object.class, JdbcType.FLOAT, new FloatTypeHandler()); - - handlerRegistry.register(Object.class, JdbcType.DOUBLE, new DoubleTypeHandler()); - - handlerRegistry.register(Object.class, JdbcType.CHAR, new StringTypeHandler()); - handlerRegistry.register(Object.class, JdbcType.CLOB, new ClobTypeHandler()); - handlerRegistry.register(Object.class, JdbcType.VARCHAR, new StringTypeHandler()); - handlerRegistry.register(Object.class, JdbcType.LONGVARCHAR, new StringTypeHandler()); - handlerRegistry.register(Object.class, JdbcType.NVARCHAR, new NStringTypeHandler()); - handlerRegistry.register(Object.class, JdbcType.NCHAR, new NStringTypeHandler()); - handlerRegistry.register(Object.class, JdbcType.NCLOB, new NClobTypeHandler()); - - handlerRegistry.register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler()); - - handlerRegistry.register(Object.class, JdbcType.BIGINT, new LongTypeHandler()); - - handlerRegistry.register(Object.class, JdbcType.REAL, new BigDecimalTypeHandler()); - handlerRegistry.register(Object.class, JdbcType.DECIMAL, new BigDecimalTypeHandler()); - handlerRegistry.register(Object.class, JdbcType.NUMERIC, new BigDecimalTypeHandler()); - - handlerRegistry.register(Object.class, JdbcType.BLOB, new BlobInputStreamTypeHandler()); - handlerRegistry.register(Object.class, JdbcType.LONGVARBINARY, new BlobTypeHandler()); - - handlerRegistry.register(Object.class, JdbcType.DATE, new DateOnlyTypeHandler()); - handlerRegistry.register(Object.class, JdbcType.TIME, new TimeOnlyTypeHandler()); - handlerRegistry.register(Object.class, JdbcType.TIMESTAMP, new DateTypeHandler()); - - handlerRegistry.register(Object.class, JdbcType.SQLXML, new SqlxmlTypeHandler()); - } - - public void initCustomMybatisInterceptors(Configuration configuration) { - if (customMybatisInterceptors!=null){ - for (Interceptor interceptor :customMybatisInterceptors){ - configuration.addInterceptor(interceptor); - } - } - } - - public void initMyBatisLogSqlExecutionTimePlugin(Configuration configuration) { - configuration.addInterceptor(new LogSqlExecutionTimePlugin()); - } - - public Configuration parseMybatisConfiguration(XMLConfigBuilder parser) { - Configuration configuration = parser.parse(); - - applyCustomMybatisCustomizations(configuration); - return configuration; - } - - protected void applyCustomMybatisCustomizations(Configuration configuration) { - initCustomMybatisMappers(configuration); - - if (dependentEngineMybatisTypeAliasConfigs != null) { - for (MybatisTypeAliasConfigurator typeAliasConfig : dependentEngineMybatisTypeAliasConfigs) { - typeAliasConfig.configure(configuration.getTypeAliasRegistry()); - } - } - if (dependentEngineMybatisTypeHandlerConfigs != null) { - for (MybatisTypeHandlerConfigurator typeHandlerConfig : dependentEngineMybatisTypeHandlerConfigs) { - typeHandlerConfig.configure(configuration.getTypeHandlerRegistry()); - } - } - - parseDependentEngineMybatisXMLMappers(configuration); - parseCustomMybatisXMLMappers(configuration); - } - - public void parseCustomMybatisXMLMappers(Configuration configuration) { - if (getCustomMybatisXMLMappers() != null) { - for (String resource : getCustomMybatisXMLMappers()) { - parseMybatisXmlMapping(configuration, resource); - } - } - } - - public void parseDependentEngineMybatisXMLMappers(Configuration configuration) { - if (getDependentEngineMyBatisXmlMappers() != null) { - for (String resource : getDependentEngineMyBatisXmlMappers()) { - parseMybatisXmlMapping(configuration, resource); - } - } - } - - protected void parseMybatisXmlMapping(Configuration configuration, String resource) { - // see XMLConfigBuilder.mapperElement() - XMLMapperBuilder mapperParser = new XMLMapperBuilder(getResourceAsStream(resource), configuration, resource, configuration.getSqlFragments()); - mapperParser.parse(); - } - - protected InputStream getResourceAsStream(String resource) { - ClassLoader classLoader = getClassLoader(); - if (classLoader != null) { - return getClassLoader().getResourceAsStream(resource); - } else { - return this.getClass().getClassLoader().getResourceAsStream(resource); - } - } - - public void setMybatisMappingFile(String file) { - this.mybatisMappingFile = file; - } - - public String getMybatisMappingFile() { - return mybatisMappingFile; - } - - public abstract InputStream getMyBatisXmlConfigurationStream(); - - public void initConfigurators() { - - allConfigurators = new ArrayList<>(); - allConfigurators.addAll(getEngineSpecificEngineConfigurators()); - - // Configurators that are explicitly added to the config - if (configurators != null) { - allConfigurators.addAll(configurators); - } - - // Auto discovery through ServiceLoader - if (enableConfiguratorServiceLoader) { - ClassLoader classLoader = getClassLoader(); - if (classLoader == null) { - classLoader = ReflectUtil.getClassLoader(); - } - - ServiceLoader configuratorServiceLoader = ServiceLoader.load(EngineConfigurator.class, classLoader); - int nrOfServiceLoadedConfigurators = 0; - for (EngineConfigurator configurator : configuratorServiceLoader) { - allConfigurators.add(configurator); - nrOfServiceLoadedConfigurators++; - } - - if (nrOfServiceLoadedConfigurators > 0) { - logger.info("Found {} auto-discoverable Process Engine Configurator{}", nrOfServiceLoadedConfigurators, nrOfServiceLoadedConfigurators > 1 ? "s" : ""); - } - - if (!allConfigurators.isEmpty()) { - - // Order them according to the priorities (useful for dependent - // configurator) - allConfigurators.sort(new Comparator() { - - @Override - public int compare(EngineConfigurator configurator1, EngineConfigurator configurator2) { - int priority1 = configurator1.getPriority(); - int priority2 = configurator2.getPriority(); - - if (priority1 < priority2) { - return -1; - } else if (priority1 > priority2) { - return 1; - } - return 0; - } - }); - - // Execute the configurators - logger.info("Found {} Engine Configurators in total:", allConfigurators.size()); - for (EngineConfigurator configurator : allConfigurators) { - logger.info("{} (priority:{})", configurator.getClass(), configurator.getPriority()); - } - - } - - } - } - - public void close() { - if (forceCloseMybatisConnectionPool && dataSource instanceof PooledDataSource) { - /* - * When the datasource is created by a Flowable engine (i.e. it's an instance of PooledDataSource), - * the connection pool needs to be closed when closing the engine. - * Note that calling forceCloseAll() multiple times (as is the case when running with multiple engine) is ok. - */ - ((PooledDataSource) dataSource).forceCloseAll(); - } - } - - protected List getEngineSpecificEngineConfigurators() { - // meant to be overridden if needed - return Collections.emptyList(); - } - - public void configuratorsBeforeInit() { - for (EngineConfigurator configurator : allConfigurators) { - logger.info("Executing beforeInit() of {} (priority:{})", configurator.getClass(), configurator.getPriority()); - configurator.beforeInit(this); - } - } - - public void configuratorsAfterInit() { - for (EngineConfigurator configurator : allConfigurators) { - logger.info("Executing configure() of {} (priority:{})", configurator.getClass(), configurator.getPriority()); - configurator.configure(this); - } - } - - public LockManager getLockManager(String lockName) { - return new LockManagerImpl(commandExecutor, lockName, getLockPollRate(), getEngineCfgKey()); - } - - // getters and setters - // ////////////////////////////////////////////////////// - - public abstract String getEngineName(); - - public ClassLoader getClassLoader() { - return classLoader; - } - - public AbstractEngineConfiguration setClassLoader(ClassLoader classLoader) { - this.classLoader = classLoader; - return this; - } - - public boolean isUseClassForNameClassLoading() { - return useClassForNameClassLoading; - } - - public AbstractEngineConfiguration setUseClassForNameClassLoading(boolean useClassForNameClassLoading) { - this.useClassForNameClassLoading = useClassForNameClassLoading; - return this; - } - - public void addEngineLifecycleListener(EngineLifecycleListener engineLifecycleListener) { - if (this.engineLifecycleListeners == null) { - this.engineLifecycleListeners = new ArrayList<>(); - } - this.engineLifecycleListeners.add(engineLifecycleListener); - } - - public List getEngineLifecycleListeners() { - return engineLifecycleListeners; - } - - public AbstractEngineConfiguration setEngineLifecycleListeners(List engineLifecycleListeners) { - this.engineLifecycleListeners = engineLifecycleListeners; - return this; - } - - public String getDatabaseType() { - return databaseType; - } - - public AbstractEngineConfiguration setDatabaseType(String databaseType) { - this.databaseType = databaseType; - return this; - } - - public DataSource getDataSource() { - return dataSource; - } - - public AbstractEngineConfiguration setDataSource(DataSource dataSource) { - this.dataSource = dataSource; - return this; - } - - public SchemaManager getSchemaManager() { - return schemaManager; - } - - public AbstractEngineConfiguration setSchemaManager(SchemaManager schemaManager) { - this.schemaManager = schemaManager; - return this; - } - - public SchemaManager getCommonSchemaManager() { - return commonSchemaManager; - } - - public AbstractEngineConfiguration setCommonSchemaManager(SchemaManager commonSchemaManager) { - this.commonSchemaManager = commonSchemaManager; - return this; - } - - public Command getSchemaManagementCmd() { - return schemaManagementCmd; - } - - public AbstractEngineConfiguration setSchemaManagementCmd(Command schemaManagementCmd) { - this.schemaManagementCmd = schemaManagementCmd; - return this; - } - - public String getJdbcDriver() { - return jdbcDriver; - } - - public AbstractEngineConfiguration setJdbcDriver(String jdbcDriver) { - this.jdbcDriver = jdbcDriver; - return this; - } - - public String getJdbcUrl() { - return jdbcUrl; - } - - public AbstractEngineConfiguration setJdbcUrl(String jdbcUrl) { - this.jdbcUrl = jdbcUrl; - return this; - } - - public String getJdbcUsername() { - return jdbcUsername; - } - - public AbstractEngineConfiguration setJdbcUsername(String jdbcUsername) { - this.jdbcUsername = jdbcUsername; - return this; - } - - public String getJdbcPassword() { - return jdbcPassword; - } - - public AbstractEngineConfiguration setJdbcPassword(String jdbcPassword) { - this.jdbcPassword = jdbcPassword; - return this; - } - - public int getJdbcMaxActiveConnections() { - return jdbcMaxActiveConnections; - } - - public AbstractEngineConfiguration setJdbcMaxActiveConnections(int jdbcMaxActiveConnections) { - this.jdbcMaxActiveConnections = jdbcMaxActiveConnections; - return this; - } - - public int getJdbcMaxIdleConnections() { - return jdbcMaxIdleConnections; - } - - public AbstractEngineConfiguration setJdbcMaxIdleConnections(int jdbcMaxIdleConnections) { - this.jdbcMaxIdleConnections = jdbcMaxIdleConnections; - return this; - } - - public int getJdbcMaxCheckoutTime() { - return jdbcMaxCheckoutTime; - } - - public AbstractEngineConfiguration setJdbcMaxCheckoutTime(int jdbcMaxCheckoutTime) { - this.jdbcMaxCheckoutTime = jdbcMaxCheckoutTime; - return this; - } - - public int getJdbcMaxWaitTime() { - return jdbcMaxWaitTime; - } - - public AbstractEngineConfiguration setJdbcMaxWaitTime(int jdbcMaxWaitTime) { - this.jdbcMaxWaitTime = jdbcMaxWaitTime; - return this; - } - - public boolean isJdbcPingEnabled() { - return jdbcPingEnabled; - } - - public AbstractEngineConfiguration setJdbcPingEnabled(boolean jdbcPingEnabled) { - this.jdbcPingEnabled = jdbcPingEnabled; - return this; - } - - public int getJdbcPingConnectionNotUsedFor() { - return jdbcPingConnectionNotUsedFor; - } - - public AbstractEngineConfiguration setJdbcPingConnectionNotUsedFor(int jdbcPingConnectionNotUsedFor) { - this.jdbcPingConnectionNotUsedFor = jdbcPingConnectionNotUsedFor; - return this; - } - - public int getJdbcDefaultTransactionIsolationLevel() { - return jdbcDefaultTransactionIsolationLevel; - } - - public AbstractEngineConfiguration setJdbcDefaultTransactionIsolationLevel(int jdbcDefaultTransactionIsolationLevel) { - this.jdbcDefaultTransactionIsolationLevel = jdbcDefaultTransactionIsolationLevel; - return this; - } - - public String getJdbcPingQuery() { - return jdbcPingQuery; - } - - public AbstractEngineConfiguration setJdbcPingQuery(String jdbcPingQuery) { - this.jdbcPingQuery = jdbcPingQuery; - return this; - } - - public String getDataSourceJndiName() { - return dataSourceJndiName; - } - - public AbstractEngineConfiguration setDataSourceJndiName(String dataSourceJndiName) { - this.dataSourceJndiName = dataSourceJndiName; - return this; - } - - public CommandConfig getSchemaCommandConfig() { - return schemaCommandConfig; - } - - public AbstractEngineConfiguration setSchemaCommandConfig(CommandConfig schemaCommandConfig) { - this.schemaCommandConfig = schemaCommandConfig; - return this; - } - - public boolean isTransactionsExternallyManaged() { - return transactionsExternallyManaged; - } - - public AbstractEngineConfiguration setTransactionsExternallyManaged(boolean transactionsExternallyManaged) { - this.transactionsExternallyManaged = transactionsExternallyManaged; - return this; - } - - public Map getBeans() { - return beans; - } - - public AbstractEngineConfiguration setBeans(Map beans) { - this.beans = beans; - return this; - } - - public IdGenerator getIdGenerator() { - return idGenerator; - } - - public AbstractEngineConfiguration setIdGenerator(IdGenerator idGenerator) { - this.idGenerator = idGenerator; - return this; - } - - public boolean isUsePrefixId() { - return usePrefixId; - } - - public AbstractEngineConfiguration setUsePrefixId(boolean usePrefixId) { - this.usePrefixId = usePrefixId; - return this; - } - - public String getXmlEncoding() { - return xmlEncoding; - } - - public AbstractEngineConfiguration setXmlEncoding(String xmlEncoding) { - this.xmlEncoding = xmlEncoding; - return this; - } - - public CommandConfig getDefaultCommandConfig() { - return defaultCommandConfig; - } - - public AbstractEngineConfiguration setDefaultCommandConfig(CommandConfig defaultCommandConfig) { - this.defaultCommandConfig = defaultCommandConfig; - return this; - } - - public CommandExecutor getCommandExecutor() { - return commandExecutor; - } - - public AbstractEngineConfiguration setCommandExecutor(CommandExecutor commandExecutor) { - this.commandExecutor = commandExecutor; - return this; - } - - public CommandContextFactory getCommandContextFactory() { - return commandContextFactory; - } - - public AbstractEngineConfiguration setCommandContextFactory(CommandContextFactory commandContextFactory) { - this.commandContextFactory = commandContextFactory; - return this; - } - - public CommandInterceptor getCommandInvoker() { - return commandInvoker; - } - - public AbstractEngineConfiguration setCommandInvoker(CommandInterceptor commandInvoker) { - this.commandInvoker = commandInvoker; - return this; - } - - public AgendaOperationRunner getAgendaOperationRunner() { - return agendaOperationRunner; - } - - public AbstractEngineConfiguration setAgendaOperationRunner(AgendaOperationRunner agendaOperationRunner) { - this.agendaOperationRunner = agendaOperationRunner; - return this; - } - - public List getCustomPreCommandInterceptors() { - return customPreCommandInterceptors; - } - - public AbstractEngineConfiguration setCustomPreCommandInterceptors(List customPreCommandInterceptors) { - this.customPreCommandInterceptors = customPreCommandInterceptors; - return this; - } - - public List getCustomPostCommandInterceptors() { - return customPostCommandInterceptors; - } - - public AbstractEngineConfiguration setCustomPostCommandInterceptors(List customPostCommandInterceptors) { - this.customPostCommandInterceptors = customPostCommandInterceptors; - return this; - } - - public List getCommandInterceptors() { - return commandInterceptors; - } - - public AbstractEngineConfiguration setCommandInterceptors(List commandInterceptors) { - this.commandInterceptors = commandInterceptors; - return this; - } - - public Map getEngineConfigurations() { - return engineConfigurations; - } - - public AbstractEngineConfiguration setEngineConfigurations(Map engineConfigurations) { - this.engineConfigurations = engineConfigurations; - return this; - } - - public void addEngineConfiguration(String key, String scopeType, AbstractEngineConfiguration engineConfiguration) { - if (engineConfigurations == null) { - engineConfigurations = new HashMap<>(); - } - engineConfigurations.put(key, engineConfiguration); - engineConfigurations.put(scopeType, engineConfiguration); - } - - public Map getServiceConfigurations() { - return serviceConfigurations; - } - - public AbstractEngineConfiguration setServiceConfigurations(Map serviceConfigurations) { - this.serviceConfigurations = serviceConfigurations; - return this; - } - - public void addServiceConfiguration(String key, AbstractServiceConfiguration serviceConfiguration) { - if (serviceConfigurations == null) { - serviceConfigurations = new HashMap<>(); - } - serviceConfigurations.put(key, serviceConfiguration); - } - - public Map getEventRegistryEventConsumers() { - return eventRegistryEventConsumers; - } - - public AbstractEngineConfiguration setEventRegistryEventConsumers(Map eventRegistryEventConsumers) { - this.eventRegistryEventConsumers = eventRegistryEventConsumers; - return this; - } - - public void addEventRegistryEventConsumer(String key, EventRegistryEventConsumer eventRegistryEventConsumer) { - if (eventRegistryEventConsumers == null) { - eventRegistryEventConsumers = new HashMap<>(); - } - eventRegistryEventConsumers.put(key, eventRegistryEventConsumer); - } - - public AbstractEngineConfiguration setDefaultCommandInterceptors(Collection defaultCommandInterceptors) { - this.defaultCommandInterceptors = defaultCommandInterceptors; - return this; - } - - public SqlSessionFactory getSqlSessionFactory() { - return sqlSessionFactory; - } - - public AbstractEngineConfiguration setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { - this.sqlSessionFactory = sqlSessionFactory; - return this; - } - - public boolean isDbHistoryUsed() { - return isDbHistoryUsed; - } - - public AbstractEngineConfiguration setDbHistoryUsed(boolean isDbHistoryUsed) { - this.isDbHistoryUsed = isDbHistoryUsed; - return this; - } - - public DbSqlSessionFactory getDbSqlSessionFactory() { - return dbSqlSessionFactory; - } - - public AbstractEngineConfiguration setDbSqlSessionFactory(DbSqlSessionFactory dbSqlSessionFactory) { - this.dbSqlSessionFactory = dbSqlSessionFactory; - return this; - } - - public TransactionFactory getTransactionFactory() { - return transactionFactory; - } - - public AbstractEngineConfiguration setTransactionFactory(TransactionFactory transactionFactory) { - this.transactionFactory = transactionFactory; - return this; - } - - public TransactionContextFactory getTransactionContextFactory() { - return transactionContextFactory; - } - - public AbstractEngineConfiguration setTransactionContextFactory(TransactionContextFactory transactionContextFactory) { - this.transactionContextFactory = transactionContextFactory; - return this; - } - - public int getMaxNrOfStatementsInBulkInsert() { - return maxNrOfStatementsInBulkInsert; - } - - public AbstractEngineConfiguration setMaxNrOfStatementsInBulkInsert(int maxNrOfStatementsInBulkInsert) { - this.maxNrOfStatementsInBulkInsert = maxNrOfStatementsInBulkInsert; - return this; - } - - public boolean isBulkInsertEnabled() { - return isBulkInsertEnabled; - } - - public AbstractEngineConfiguration setBulkInsertEnabled(boolean isBulkInsertEnabled) { - this.isBulkInsertEnabled = isBulkInsertEnabled; - return this; - } - - public Set> getCustomMybatisMappers() { - return customMybatisMappers; - } - - public AbstractEngineConfiguration setCustomMybatisMappers(Set> customMybatisMappers) { - this.customMybatisMappers = customMybatisMappers; - return this; - } - - public Set getCustomMybatisXMLMappers() { - return customMybatisXMLMappers; - } - - public AbstractEngineConfiguration setCustomMybatisXMLMappers(Set customMybatisXMLMappers) { - this.customMybatisXMLMappers = customMybatisXMLMappers; - return this; - } - - public Set getDependentEngineMyBatisXmlMappers() { - return dependentEngineMyBatisXmlMappers; - } - - public AbstractEngineConfiguration setCustomMybatisInterceptors(List customMybatisInterceptors) { - this.customMybatisInterceptors = customMybatisInterceptors; - return this; - } - - public List getCustomMybatisInterceptors() { - return customMybatisInterceptors; - } - - public AbstractEngineConfiguration setDependentEngineMyBatisXmlMappers(Set dependentEngineMyBatisXmlMappers) { - this.dependentEngineMyBatisXmlMappers = dependentEngineMyBatisXmlMappers; - return this; - } - - public List getDependentEngineMybatisTypeAliasConfigs() { - return dependentEngineMybatisTypeAliasConfigs; - } - - public AbstractEngineConfiguration setDependentEngineMybatisTypeAliasConfigs(List dependentEngineMybatisTypeAliasConfigs) { - this.dependentEngineMybatisTypeAliasConfigs = dependentEngineMybatisTypeAliasConfigs; - return this; - } - - public List getDependentEngineMybatisTypeHandlerConfigs() { - return dependentEngineMybatisTypeHandlerConfigs; - } - - public AbstractEngineConfiguration setDependentEngineMybatisTypeHandlerConfigs(List dependentEngineMybatisTypeHandlerConfigs) { - this.dependentEngineMybatisTypeHandlerConfigs = dependentEngineMybatisTypeHandlerConfigs; - return this; - } - - public List getCustomSessionFactories() { - return customSessionFactories; - } - - public AbstractEngineConfiguration addCustomSessionFactory(SessionFactory sessionFactory) { - if (customSessionFactories == null) { - customSessionFactories = new ArrayList<>(); - } - customSessionFactories.add(sessionFactory); - return this; - } - - public AbstractEngineConfiguration setCustomSessionFactories(List customSessionFactories) { - this.customSessionFactories = customSessionFactories; - return this; - } - - public boolean isUsingRelationalDatabase() { - return usingRelationalDatabase; - } - - public AbstractEngineConfiguration setUsingRelationalDatabase(boolean usingRelationalDatabase) { - this.usingRelationalDatabase = usingRelationalDatabase; - return this; - } - - public boolean isUsingSchemaMgmt() { - return usingSchemaMgmt; - } - - public AbstractEngineConfiguration setUsingSchemaMgmt(boolean usingSchema) { - this.usingSchemaMgmt = usingSchema; - return this; - } - - public String getDatabaseTablePrefix() { - return databaseTablePrefix; - } - - public AbstractEngineConfiguration setDatabaseTablePrefix(String databaseTablePrefix) { - this.databaseTablePrefix = databaseTablePrefix; - return this; - } - - public String getDatabaseWildcardEscapeCharacter() { - return databaseWildcardEscapeCharacter; - } - - public AbstractEngineConfiguration setDatabaseWildcardEscapeCharacter(String databaseWildcardEscapeCharacter) { - this.databaseWildcardEscapeCharacter = databaseWildcardEscapeCharacter; - return this; - } - - public String getDatabaseCatalog() { - return databaseCatalog; - } - - public AbstractEngineConfiguration setDatabaseCatalog(String databaseCatalog) { - this.databaseCatalog = databaseCatalog; - return this; - } - - public String getDatabaseSchema() { - return databaseSchema; - } - - public AbstractEngineConfiguration setDatabaseSchema(String databaseSchema) { - this.databaseSchema = databaseSchema; - return this; - } - - public boolean isTablePrefixIsSchema() { - return tablePrefixIsSchema; - } - - public AbstractEngineConfiguration setTablePrefixIsSchema(boolean tablePrefixIsSchema) { - this.tablePrefixIsSchema = tablePrefixIsSchema; - return this; - } - - public boolean isAlwaysLookupLatestDefinitionVersion() { - return alwaysLookupLatestDefinitionVersion; - } - - public AbstractEngineConfiguration setAlwaysLookupLatestDefinitionVersion(boolean alwaysLookupLatestDefinitionVersion) { - this.alwaysLookupLatestDefinitionVersion = alwaysLookupLatestDefinitionVersion; - return this; - } - - public boolean isFallbackToDefaultTenant() { - return fallbackToDefaultTenant; - } - - public AbstractEngineConfiguration setFallbackToDefaultTenant(boolean fallbackToDefaultTenant) { - this.fallbackToDefaultTenant = fallbackToDefaultTenant; - return this; - } - - /** - * @return name of the default tenant - * @deprecated use {@link AbstractEngineConfiguration#getDefaultTenantProvider()} instead - */ - @Deprecated - public String getDefaultTenantValue() { - return getDefaultTenantProvider().getDefaultTenant(null, null, null); - } - - public AbstractEngineConfiguration setDefaultTenantValue(String defaultTenantValue) { - this.defaultTenantProvider = (tenantId, scope, scopeKey) -> defaultTenantValue; - return this; - } - - public DefaultTenantProvider getDefaultTenantProvider() { - return defaultTenantProvider; - } - - public AbstractEngineConfiguration setDefaultTenantProvider(DefaultTenantProvider defaultTenantProvider) { - this.defaultTenantProvider = defaultTenantProvider; - return this; - } - - public boolean isEnableLogSqlExecutionTime() { - return enableLogSqlExecutionTime; - } - - public void setEnableLogSqlExecutionTime(boolean enableLogSqlExecutionTime) { - this.enableLogSqlExecutionTime = enableLogSqlExecutionTime; - } - - public Map, SessionFactory> getSessionFactories() { - return sessionFactories; - } - - public AbstractEngineConfiguration setSessionFactories(Map, SessionFactory> sessionFactories) { - this.sessionFactories = sessionFactories; - return this; - } - - public String getDatabaseSchemaUpdate() { - return databaseSchemaUpdate; - } - - public AbstractEngineConfiguration setDatabaseSchemaUpdate(String databaseSchemaUpdate) { - this.databaseSchemaUpdate = databaseSchemaUpdate; - return this; - } - - public boolean isUseLockForDatabaseSchemaUpdate() { - return useLockForDatabaseSchemaUpdate; - } - - public AbstractEngineConfiguration setUseLockForDatabaseSchemaUpdate(boolean useLockForDatabaseSchemaUpdate) { - this.useLockForDatabaseSchemaUpdate = useLockForDatabaseSchemaUpdate; - return this; - } - - public boolean isEnableEventDispatcher() { - return enableEventDispatcher; - } - - public AbstractEngineConfiguration setEnableEventDispatcher(boolean enableEventDispatcher) { - this.enableEventDispatcher = enableEventDispatcher; - return this; - } - - public FlowableEventDispatcher getEventDispatcher() { - return eventDispatcher; - } - - public AbstractEngineConfiguration setEventDispatcher(FlowableEventDispatcher eventDispatcher) { - this.eventDispatcher = eventDispatcher; - return this; - } - - public List getEventListeners() { - return eventListeners; - } - - public AbstractEngineConfiguration setEventListeners(List eventListeners) { - this.eventListeners = eventListeners; - return this; - } - - public Map> getTypedEventListeners() { - return typedEventListeners; - } - - public AbstractEngineConfiguration setTypedEventListeners(Map> typedEventListeners) { - this.typedEventListeners = typedEventListeners; - return this; - } - - public List getAdditionalEventDispatchActions() { - return additionalEventDispatchActions; - } - - public AbstractEngineConfiguration setAdditionalEventDispatchActions(List additionalEventDispatchActions) { - this.additionalEventDispatchActions = additionalEventDispatchActions; - return this; - } - - public void initEventDispatcher() { - if (this.eventDispatcher == null) { - this.eventDispatcher = new FlowableEventDispatcherImpl(); - } - - initAdditionalEventDispatchActions(); - - this.eventDispatcher.setEnabled(enableEventDispatcher); - - initEventListeners(); - initTypedEventListeners(); - } - - protected void initEventListeners() { - if (eventListeners != null) { - for (FlowableEventListener listenerToAdd : eventListeners) { - this.eventDispatcher.addEventListener(listenerToAdd); - } - } - } - - protected void initAdditionalEventDispatchActions() { - if (this.additionalEventDispatchActions == null) { - this.additionalEventDispatchActions = new ArrayList<>(); - } - } - - protected void initTypedEventListeners() { - if (typedEventListeners != null) { - for (Map.Entry> listenersToAdd : typedEventListeners.entrySet()) { - // Extract types from the given string - FlowableEngineEventType[] types = FlowableEngineEventType.getTypesFromString(listenersToAdd.getKey()); - - for (FlowableEventListener listenerToAdd : listenersToAdd.getValue()) { - this.eventDispatcher.addEventListener(listenerToAdd, types); - } - } - } - } - - public boolean isLoggingSessionEnabled() { - return loggingListener != null; - } - - public LoggingListener getLoggingListener() { - return loggingListener; - } - - public void setLoggingListener(LoggingListener loggingListener) { - this.loggingListener = loggingListener; - } - - public Clock getClock() { - return clock; - } - - public AbstractEngineConfiguration setClock(Clock clock) { - this.clock = clock; - return this; - } - - public ObjectMapper getObjectMapper() { - return objectMapper; - } - - public AbstractEngineConfiguration setObjectMapper(ObjectMapper objectMapper) { - this.objectMapper = objectMapper; - return this; - } - - public int getMaxLengthString() { - if (maxLengthStringVariableType == -1) { - if ("oracle".equalsIgnoreCase(databaseType)) { - return DEFAULT_ORACLE_MAX_LENGTH_STRING; - } else { - return DEFAULT_GENERIC_MAX_LENGTH_STRING; - } - } else { - return maxLengthStringVariableType; - } - } - - public int getMaxLengthStringVariableType() { - return maxLengthStringVariableType; - } - - public AbstractEngineConfiguration setMaxLengthStringVariableType(int maxLengthStringVariableType) { - this.maxLengthStringVariableType = maxLengthStringVariableType; - return this; - } - - public PropertyDataManager getPropertyDataManager() { - return propertyDataManager; - } - - public Duration getLockPollRate() { - return lockPollRate; - } - - public AbstractEngineConfiguration setLockPollRate(Duration lockPollRate) { - this.lockPollRate = lockPollRate; - return this; - } - - public Duration getSchemaLockWaitTime() { - return schemaLockWaitTime; - } - - public void setSchemaLockWaitTime(Duration schemaLockWaitTime) { - this.schemaLockWaitTime = schemaLockWaitTime; - } - - public AbstractEngineConfiguration setPropertyDataManager(PropertyDataManager propertyDataManager) { - this.propertyDataManager = propertyDataManager; - return this; - } - - public PropertyEntityManager getPropertyEntityManager() { - return propertyEntityManager; - } - - public AbstractEngineConfiguration setPropertyEntityManager(PropertyEntityManager propertyEntityManager) { - this.propertyEntityManager = propertyEntityManager; - return this; - } - - public ByteArrayDataManager getByteArrayDataManager() { - return byteArrayDataManager; - } - - public AbstractEngineConfiguration setByteArrayDataManager(ByteArrayDataManager byteArrayDataManager) { - this.byteArrayDataManager = byteArrayDataManager; - return this; - } - - public ByteArrayEntityManager getByteArrayEntityManager() { - return byteArrayEntityManager; - } - - public AbstractEngineConfiguration setByteArrayEntityManager(ByteArrayEntityManager byteArrayEntityManager) { - this.byteArrayEntityManager = byteArrayEntityManager; - return this; - } - - public TableDataManager getTableDataManager() { - return tableDataManager; - } - - public AbstractEngineConfiguration setTableDataManager(TableDataManager tableDataManager) { - this.tableDataManager = tableDataManager; - return this; - } - - public List getDeployers() { - return deployers; - } - - public AbstractEngineConfiguration setDeployers(List deployers) { - this.deployers = deployers; - return this; - } - - public List getCustomPreDeployers() { - return customPreDeployers; - } - - public AbstractEngineConfiguration setCustomPreDeployers(List customPreDeployers) { - this.customPreDeployers = customPreDeployers; - return this; - } - - public List getCustomPostDeployers() { - return customPostDeployers; - } - - public AbstractEngineConfiguration setCustomPostDeployers(List customPostDeployers) { - this.customPostDeployers = customPostDeployers; - return this; - } - - public boolean isEnableConfiguratorServiceLoader() { - return enableConfiguratorServiceLoader; - } - - public AbstractEngineConfiguration setEnableConfiguratorServiceLoader(boolean enableConfiguratorServiceLoader) { - this.enableConfiguratorServiceLoader = enableConfiguratorServiceLoader; - return this; - } - - public List getConfigurators() { - return configurators; - } - - public AbstractEngineConfiguration addConfigurator(EngineConfigurator configurator) { - if (configurators == null) { - configurators = new ArrayList<>(); - } - configurators.add(configurator); - return this; - } - - /** - * @return All {@link EngineConfigurator} instances. Will only contain values after init of the engine. - * Use the {@link #getConfigurators()} or {@link #addConfigurator(EngineConfigurator)} methods otherwise. - */ - public List getAllConfigurators() { - return allConfigurators; - } - - public AbstractEngineConfiguration setConfigurators(List configurators) { - this.configurators = configurators; - return this; - } - - public EngineConfigurator getIdmEngineConfigurator() { - return idmEngineConfigurator; - } - - public AbstractEngineConfiguration setIdmEngineConfigurator(EngineConfigurator idmEngineConfigurator) { - this.idmEngineConfigurator = idmEngineConfigurator; - return this; - } - - public EngineConfigurator getEventRegistryConfigurator() { - return eventRegistryConfigurator; - } - - public AbstractEngineConfiguration setEventRegistryConfigurator(EngineConfigurator eventRegistryConfigurator) { - this.eventRegistryConfigurator = eventRegistryConfigurator; - return this; - } - - public AbstractEngineConfiguration setForceCloseMybatisConnectionPool(boolean forceCloseMybatisConnectionPool) { - this.forceCloseMybatisConnectionPool = forceCloseMybatisConnectionPool; - return this; - } - - public boolean isForceCloseMybatisConnectionPool() { - return forceCloseMybatisConnectionPool; - } -} diff --git a/sql/db2/flowable-patch/src/main/resources/META-INF/package-info.md b/sql/db2/flowable-patch/src/main/resources/META-INF/package-info.md deleted file mode 100644 index 1932c7a3f..000000000 --- a/sql/db2/flowable-patch/src/main/resources/META-INF/package-info.md +++ /dev/null @@ -1 +0,0 @@ -防止IDEA将`.`和`/`混为一谈 \ No newline at end of file diff --git a/sql/db2/flowable-patch/src/main/resources/META-INF/services/liquibase.database.Database b/sql/db2/flowable-patch/src/main/resources/META-INF/services/liquibase.database.Database deleted file mode 100644 index efbcfcca2..000000000 --- a/sql/db2/flowable-patch/src/main/resources/META-INF/services/liquibase.database.Database +++ /dev/null @@ -1,21 +0,0 @@ -liquibase.database.core.CockroachDatabase -liquibase.database.core.DB2Database -liquibase.database.core.Db2zDatabase -liquibase.database.core.DerbyDatabase -liquibase.database.core.Firebird3Database -liquibase.database.core.FirebirdDatabase -liquibase.database.core.H2Database -liquibase.database.core.HsqlDatabase -liquibase.database.core.InformixDatabase -liquibase.database.core.Ingres9Database -liquibase.database.core.MSSQLDatabase -liquibase.database.core.MariaDBDatabase -liquibase.database.core.MockDatabase -liquibase.database.core.MySQLDatabase -liquibase.database.core.OracleDatabase -liquibase.database.core.PostgresDatabase -liquibase.database.core.SQLiteDatabase -liquibase.database.core.SybaseASADatabase -liquibase.database.core.SybaseDatabase -liquibase.database.core.DmDatabase -liquibase.database.core.UnsupportedDatabase diff --git a/sql/mysql/ruoyi-vue-pro.sql b/sql/mysql/ruoyi-vue-pro.sql index 95923d4eb..f7b7c292c 100644 --- a/sql/mysql/ruoyi-vue-pro.sql +++ b/sql/mysql/ruoyi-vue-pro.sql @@ -11,7 +11,7 @@ Target Server Version : 80200 (8.2.0) File Encoding : 65001 - Date: 30/03/2024 20:42:06 + Date: 03/04/2024 19:07:31 */ SET NAMES utf8mb4; @@ -327,9 +327,13 @@ CREATE TABLE `infra_api_access_log` ( `application_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '应用名', `request_method` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求方法名', `request_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求地址', - `request_params` varchar(8000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求参数', + `request_params` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '请求参数', + `response_body` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '响应结果', `user_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户 IP', `user_agent` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '浏览器 UA', + `operate_module` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '操作模块', + `operate_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '操作名', + `operate_type` tinyint NULL DEFAULT 0 COMMENT '操作分类', `begin_time` datetime NOT NULL COMMENT '开始请求时间', `end_time` datetime NOT NULL COMMENT '结束请求时间', `duration` int NOT NULL COMMENT '执行时长', @@ -343,7 +347,7 @@ CREATE TABLE `infra_api_access_log` ( `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_create_time`(`create_time` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 35832 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'API 访问日志表'; +) ENGINE = InnoDB AUTO_INCREMENT = 35920 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'API 访问日志表'; -- ---------------------------- -- Records of infra_api_access_log @@ -385,7 +389,7 @@ CREATE TABLE `infra_api_error_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 16429 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; +) ENGINE = InnoDB AUTO_INCREMENT = 16462 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; -- ---------------------------- -- Records of infra_api_error_log @@ -494,7 +498,7 @@ CREATE TABLE `infra_config` ( -- Records of infra_config -- ---------------------------- BEGIN; -INSERT INTO `infra_config` (`id`, `category`, `type`, `name`, `config_key`, `value`, `visible`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, 'biz', 1, '用户管理-账号初始密码', 'sys.user.init-password', '123456', b'0', '初始化密码 123456', 'admin', '2021-01-05 17:03:48', '1', '2024-02-28 22:54:14', b'0'); +INSERT INTO `infra_config` (`id`, `category`, `type`, `name`, `config_key`, `value`, `visible`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, 'biz', 1, '用户管理-账号初始密码', 'sys.user.init-password', '123456', b'0', '初始化密码 123456', 'admin', '2021-01-05 17:03:48', '1', '2024-04-03 17:22:28', b'0'); INSERT INTO `infra_config` (`id`, `category`, `type`, `name`, `config_key`, `value`, `visible`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (7, 'url', 2, 'MySQL 监控的地址', 'url.druid', '', b'1', '', '1', '2023-04-07 13:41:16', '1', '2023-04-07 14:33:38', b'0'); INSERT INTO `infra_config` (`id`, `category`, `type`, `name`, `config_key`, `value`, `visible`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (8, 'url', 2, 'SkyWalking 监控的地址', 'url.skywalking', '', b'1', '', '1', '2023-04-07 13:41:16', '1', '2023-04-07 14:57:03', b'0'); INSERT INTO `infra_config` (`id`, `category`, `type`, `name`, `config_key`, `value`, `visible`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (9, 'url', 2, 'Spring Boot Admin 监控的地址', 'url.spring-boot-admin', '', b'1', '', '1', '2023-04-07 13:41:16', '1', '2023-04-07 14:52:07', b'0'); @@ -690,7 +694,7 @@ CREATE TABLE `infra_file` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1301 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1302 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; -- ---------------------------- -- Records of infra_file @@ -1416,7 +1420,7 @@ CREATE TABLE `system_login_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 3054 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 3066 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; -- ---------------------------- -- Records of system_login_log @@ -2453,7 +2457,7 @@ CREATE TABLE `system_oauth2_access_token` ( PRIMARY KEY (`id`) USING BTREE, INDEX `idx_access_token`(`access_token` ASC) USING BTREE, INDEX `idx_refresh_token`(`refresh_token` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 6332 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; +) ENGINE = InnoDB AUTO_INCREMENT = 6366 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; -- ---------------------------- -- Records of system_oauth2_access_token @@ -2575,7 +2579,7 @@ CREATE TABLE `system_oauth2_refresh_token` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1430 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; +) ENGINE = InnoDB AUTO_INCREMENT = 1441 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; -- ---------------------------- -- Records of system_oauth2_refresh_token @@ -2615,7 +2619,7 @@ CREATE TABLE `system_operate_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 11964 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 12000 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录'; -- ---------------------------- -- Records of system_operate_log @@ -5305,7 +5309,7 @@ CREATE TABLE `system_sms_log` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 946 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志'; +) ENGINE = InnoDB AUTO_INCREMENT = 947 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志'; -- ---------------------------- -- Records of system_sms_log @@ -5475,7 +5479,7 @@ INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `c INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (151, '大租户', 126, '土豆大', NULL, 0, 'https://tudou.iocoder.cn', 111, '2023-12-08 00:00:00', 10, '1', '2023-12-02 23:35:05', '1', '2023-12-08 23:39:56', b'0'); INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (152, '新租户', 127, '土豆', NULL, 0, 'http://xx.iocoder.cn', 111, '2025-12-31 00:00:00', 50, '1', '2023-12-30 11:43:17', '1', '2023-12-30 11:43:17', b'0'); INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (153, '小明的租户', 128, 'xiaoming', '15601691301', 0, 'xiaoming.iocoder.cn', 111, '2025-12-01 00:00:00', 100, '1', '2024-02-27 21:58:25', '1', '2024-02-28 22:53:54', b'0'); -INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (154, 'hh', 129, 'hh', NULL, 0, 'http://hh.iocoder.cn', 111, '2024-04-30 00:00:00', 123, '1', '2024-03-30 17:52:59', '1', '2024-03-30 17:52:59', b'0'); +INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (154, 'hh', 129, 'hh', NULL, 0, 'http://hh.iocoder.cn', 111, '2024-04-30 00:00:00', 123, '1', '2024-03-30 17:52:59', '1', '2024-04-03 15:06:42', b'0'); COMMIT; -- ---------------------------- @@ -5619,7 +5623,7 @@ CREATE TABLE `system_users` ( -- Records of system_users -- ---------------------------- BEGIN; -INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '18818260277', 2, 'http://test.yudao.iocoder.cn/96c787a2ce88bf6d0ce3cd8b6cf5314e80e7703cd41bf4af8cd2e2909dbd6b6d.png', 0, '0:0:0:0:0:0:0:1', '2024-03-30 17:18:34', 'admin', '2021-01-05 17:03:47', NULL, '2024-03-30 17:18:34', b'0', 1); +INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '18818260277', 2, 'http://test.yudao.iocoder.cn/96c787a2ce88bf6d0ce3cd8b6cf5314e80e7703cd41bf4af8cd2e2909dbd6b6d.png', 0, '127.0.0.1', '2024-04-03 17:31:00', 'admin', '2021-01-05 17:03:47', NULL, '2024-04-03 17:31:00', b'0', 1); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '127.0.0.1', '2022-07-09 23:03:33', '', '2021-01-07 09:07:17', NULL, '2022-07-09 23:03:33', b'0', 1); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (103, 'yuanma', '$2a$10$YMpimV4T6BtDhIaA8jSW.u8UTGBeGhc/qwXP4oxoMr4mOw9.qttt6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '0:0:0:0:0:0:0:1', '2024-03-18 21:09:04', '', '2021-01-13 23:50:35', NULL, '2024-03-18 21:09:04', b'0', 1); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (104, 'test', '$2a$04$KhExCYl7lx6eWWZYKsibKOZ8IBJRyuNuCcEOLQ11RYhJKgHmlSwK.', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, '', 0, '0:0:0:0:0:0:0:1', '2024-03-26 07:11:35', '', '2021-01-21 02:13:53', NULL, '2024-03-26 07:11:35', b'0', 1); diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringAopUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringAopUtils.java deleted file mode 100644 index b71342cb3..000000000 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringAopUtils.java +++ /dev/null @@ -1,46 +0,0 @@ -package cn.iocoder.yudao.framework.common.util.spring; - -import cn.hutool.core.bean.BeanUtil; -import org.springframework.aop.framework.AdvisedSupport; -import org.springframework.aop.framework.AopProxy; -import org.springframework.aop.support.AopUtils; - -/** - * Spring AOP 工具类 - * - * 参考波克尔 http://www.bubuko.com/infodetail-3471885.html 实现 - */ -public class SpringAopUtils { - - /** - * 获取代理的目标对象 - * - * @param proxy 代理对象 - * @return 目标对象 - */ - public static Object getTarget(Object proxy) throws Exception { - // 不是代理对象 - if (!AopUtils.isAopProxy(proxy)) { - return proxy; - } - // Jdk 代理 - if (AopUtils.isJdkDynamicProxy(proxy)) { - return getJdkDynamicProxyTargetObject(proxy); - } - // Cglib 代理 - return getCglibProxyTargetObject(proxy); - } - - private static Object getCglibProxyTargetObject(Object proxy) throws Exception { - Object dynamicAdvisedInterceptor = BeanUtil.getFieldValue(proxy, "CGLIB$CALLBACK_0"); - AdvisedSupport advisedSupport = (AdvisedSupport) BeanUtil.getFieldValue(dynamicAdvisedInterceptor, "advised"); - return advisedSupport.getTargetSource().getTarget(); - } - - private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception { - AopProxy aopProxy = (AopProxy) BeanUtil.getFieldValue(proxy, "h"); - AdvisedSupport advisedSupport = (AdvisedSupport) BeanUtil.getFieldValue(aopProxy, "advised"); - return advisedSupport.getTargetSource().getTarget(); - } - -} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringUtils.java new file mode 100644 index 000000000..a501a7116 --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringUtils.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.framework.common.util.spring; + +import cn.hutool.extra.spring.SpringUtil; + +import java.util.Objects; + +/** + * Spring 工具类 + * + * @author 芋道源码 + */ +public class SpringUtils extends SpringUtil { + + /** + * 是否为生产环境 + * + * @return 是否生产环境 + */ + public static boolean isProd() { + String activeProfile = getActiveProfile(); + return Objects.equals("prod", activeProfile); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/package-info.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/package-info.java deleted file mode 100644 index 8c69219d0..000000000 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.framework; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java index 6ced68756..d1f7453b6 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.framework.apilog.config; import cn.iocoder.yudao.framework.apilog.core.filter.ApiAccessLogFilter; +import cn.iocoder.yudao.framework.apilog.core.interceptor.ApiAccessLogInterceptor; import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService; import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkServiceImpl; import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; @@ -10,23 +11,26 @@ import cn.iocoder.yudao.framework.web.config.WebProperties; import cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration; import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi; import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi; +import jakarta.servlet.Filter; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; - -import javax.servlet.Filter; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @AutoConfiguration(after = YudaoWebAutoConfiguration.class) -public class YudaoApiLogAutoConfiguration { +public class YudaoApiLogAutoConfiguration implements WebMvcConfigurer { @Bean + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") public ApiAccessLogFrameworkService apiAccessLogFrameworkService(ApiAccessLogApi apiAccessLogApi) { return new ApiAccessLogFrameworkServiceImpl(apiAccessLogApi); } @Bean + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") public ApiErrorLogFrameworkService apiErrorLogFrameworkService(ApiErrorLogApi apiErrorLogApi) { return new ApiErrorLogFrameworkServiceImpl(apiErrorLogApi); } @@ -49,4 +53,9 @@ public class YudaoApiLogAutoConfiguration { return bean; } + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new ApiAccessLogInterceptor()); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/annotations/ApiAccessLog.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/annotations/ApiAccessLog.java new file mode 100644 index 000000000..096c3bef2 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/annotations/ApiAccessLog.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.framework.apilog.core.annotations; + +import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 访问日志注解 + * + * @author 芋道源码 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ApiAccessLog { + + // ========== 开关字段 ========== + + /** + * 是否记录访问日志 + */ + boolean enable() default true; + /** + * 是否记录请求参数 + * + * 默认记录,主要考虑请求数据一般不大。可手动设置为 false 进行关闭 + */ + boolean requestEnable() default true; + /** + * 是否记录响应结果 + * + * 默认不记录,主要考虑响应数据可能比较大。可手动设置为 true 进行打开 + */ + boolean responseEnable() default false; + /** + * 敏感参数数组 + * + * 添加后,请求参数、响应结果不会记录该参数 + */ + String[] sanitizeKeys() default {}; + + // ========== 模块字段 ========== + + /** + * 操作模块 + * + * 为空时,会尝试读取 {@link io.swagger.v3.oas.annotations.tags.Tag#name()} 属性 + */ + String operateModule() default ""; + /** + * 操作名 + * + * 为空时,会尝试读取 {@link io.swagger.v3.oas.annotations.Operation#summary()} 属性 + */ + String operateName() default ""; + /** + * 操作分类 + * + * 实际并不是数组,因为枚举不能设置 null 作为默认值 + */ + OperateTypeEnum[] operateType() default {}; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/enums/OperateTypeEnum.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/enums/OperateTypeEnum.java new file mode 100644 index 000000000..a7f00558e --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/enums/OperateTypeEnum.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.framework.apilog.core.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 操作日志的操作类型 + * + * @author ruoyi + */ +@Getter +@AllArgsConstructor +public enum OperateTypeEnum { + + /** + * 查询 + */ + GET(1), + /** + * 新增 + */ + CREATE(2), + /** + * 修改 + */ + UPDATE(3), + /** + * 删除 + */ + DELETE(4), + /** + * 导出 + */ + EXPORT(5), + /** + * 导入 + */ + IMPORT(6), + /** + * 其它 + * + * 在无法归类时,可以选择使用其它。因为还有操作名可以进一步标识 + */ + OTHER(0); + + /** + * 类型 + */ + private final Integer type; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java index 9eea0788d..10e1381c1 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java @@ -1,38 +1,56 @@ package cn.iocoder.yudao.framework.apilog.core.filter; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.map.MapUtil; -import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLog; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog; +import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum; import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.web.config.WebProperties; import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO; +import com.fasterxml.jackson.databind.JsonNode; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.method.HandlerMethod; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; +import java.util.Iterator; import java.util.Map; +import static cn.iocoder.yudao.framework.apilog.core.interceptor.ApiAccessLogInterceptor.*; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; /** * API 访问日志 Filter * + * 目的:记录 API 访问日志到数据库中 + * * @author 芋道源码 */ @Slf4j public class ApiAccessLogFilter extends ApiRequestFilter { + private static final String[] SANITIZE_KEYS = new String[]{"password", "token", "accessToken", "refreshToken"}; + private final String applicationName; private final ApiAccessLogFrameworkService apiAccessLogFrameworkService; @@ -44,6 +62,7 @@ public class ApiAccessLogFilter extends ApiRequestFilter { } @Override + @SuppressWarnings("NullableProblems") protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 获得开始时间 @@ -66,45 +85,166 @@ public class ApiAccessLogFilter extends ApiRequestFilter { private void createApiAccessLog(HttpServletRequest request, LocalDateTime beginTime, Map queryString, String requestBody, Exception ex) { - ApiAccessLog accessLog = new ApiAccessLog(); + ApiAccessLogCreateReqDTO accessLog = new ApiAccessLogCreateReqDTO(); try { - this.buildApiAccessLogDTO(accessLog, request, beginTime, queryString, requestBody, ex); + boolean enable = buildApiAccessLog(accessLog, request, beginTime, queryString, requestBody, ex); + if (!enable) { + return; + } apiAccessLogFrameworkService.createApiAccessLog(accessLog); } catch (Throwable th) { log.error("[createApiAccessLog][url({}) log({}) 发生异常]", request.getRequestURI(), toJsonString(accessLog), th); } } - private void buildApiAccessLogDTO(ApiAccessLog accessLog, HttpServletRequest request, LocalDateTime beginTime, + private boolean buildApiAccessLog(ApiAccessLogCreateReqDTO accessLog, HttpServletRequest request, LocalDateTime beginTime, Map queryString, String requestBody, Exception ex) { + // 判断:是否要记录操作日志 + HandlerMethod handlerMethod = (HandlerMethod) request.getAttribute(ATTRIBUTE_HANDLER_METHOD); + ApiAccessLog accessLogAnnotation = null; + if (handlerMethod != null) { + accessLogAnnotation = handlerMethod.getMethodAnnotation(ApiAccessLog.class); + if (accessLogAnnotation != null && BooleanUtil.isFalse(accessLogAnnotation.enable())) { + return false; + } + } + // 处理用户信息 - accessLog.setUserId(WebFrameworkUtils.getLoginUserId(request)); - accessLog.setUserType(WebFrameworkUtils.getLoginUserType(request)); + accessLog.setUserId(WebFrameworkUtils.getLoginUserId(request)) + .setUserType(WebFrameworkUtils.getLoginUserType(request)); // 设置访问结果 CommonResult result = WebFrameworkUtils.getCommonResult(request); if (result != null) { - accessLog.setResultCode(result.getCode()); - accessLog.setResultMsg(result.getMsg()); + accessLog.setResultCode(result.getCode()).setResultMsg(result.getMsg()); } else if (ex != null) { - accessLog.setResultCode(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode()); - accessLog.setResultMsg(ExceptionUtil.getRootCauseMessage(ex)); + accessLog.setResultCode(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode()) + .setResultMsg(ExceptionUtil.getRootCauseMessage(ex)); } else { - accessLog.setResultCode(0); - accessLog.setResultMsg(""); + accessLog.setResultCode(GlobalErrorCodeConstants.SUCCESS.getCode()).setResultMsg(""); + } + // 设置请求字段 + accessLog.setTraceId(TracerUtils.getTraceId()).setApplicationName(applicationName) + .setRequestUrl(request.getRequestURI()).setRequestMethod(request.getMethod()) + .setUserAgent(ServletUtils.getUserAgent(request)).setUserIp(ServletUtils.getClientIP(request)); + String[] sanitizeKeys = accessLogAnnotation != null ? accessLogAnnotation.sanitizeKeys() : null; + Boolean requestEnable = accessLogAnnotation != null ? accessLogAnnotation.requestEnable() : Boolean.TRUE; + if (!BooleanUtil.isFalse(requestEnable)) { // 默认记录,所以判断 !false + Map requestParams = MapUtil.builder() + .put("query", sanitizeMap(queryString, sanitizeKeys)) + .put("body", sanitizeJson(requestBody, sanitizeKeys)).build(); + accessLog.setRequestParams(toJsonString(requestParams)); + } + Boolean responseEnable = accessLogAnnotation != null ? accessLogAnnotation.responseEnable() : Boolean.FALSE; + if (BooleanUtil.isTrue(responseEnable)) { // 默认不记录,默认强制要求 true + accessLog.setResponseBody(sanitizeJson(result, sanitizeKeys)); } - // 设置其它字段 - accessLog.setTraceId(TracerUtils.getTraceId()); - accessLog.setApplicationName(applicationName); - accessLog.setRequestUrl(request.getRequestURI()); - Map requestParams = MapUtil.builder().put("query", queryString).put("body", requestBody).build(); - accessLog.setRequestParams(toJsonString(requestParams)); - accessLog.setRequestMethod(request.getMethod()); - accessLog.setUserAgent(ServletUtils.getUserAgent(request)); - accessLog.setUserIp(ServletUtils.getClientIP(request)); // 持续时间 - accessLog.setBeginTime(beginTime); - accessLog.setEndTime(LocalDateTime.now()); - accessLog.setDuration((int) LocalDateTimeUtil.between(accessLog.getBeginTime(), accessLog.getEndTime(), ChronoUnit.MILLIS)); + accessLog.setBeginTime(beginTime).setEndTime(LocalDateTime.now()) + .setDuration((int) LocalDateTimeUtil.between(accessLog.getBeginTime(), accessLog.getEndTime(), ChronoUnit.MILLIS)); + + // 操作模块 + if (handlerMethod != null) { + Tag tagAnnotation = handlerMethod.getBeanType().getAnnotation(Tag.class); + Operation operationAnnotation = handlerMethod.getMethodAnnotation(Operation.class); + String operateModule = accessLogAnnotation != null ? accessLogAnnotation.operateModule() : + tagAnnotation != null ? StrUtil.nullToDefault(tagAnnotation.name(), tagAnnotation.description()) : null; + String operateName = accessLogAnnotation != null ? accessLogAnnotation.operateName() : + operationAnnotation != null ? operationAnnotation.summary() : null; + OperateTypeEnum operateType = accessLogAnnotation != null && accessLogAnnotation.operateType().length > 0 ? + accessLogAnnotation.operateType()[0] : parseOperateLogType(request); + accessLog.setOperateModule(operateModule).setOperateName(operateName).setOperateType(operateType.getType()); + } + return true; + } + + // ========== 解析 @ApiAccessLog、@Swagger 注解 ========== + + private static OperateTypeEnum parseOperateLogType(HttpServletRequest request) { + RequestMethod requestMethod = RequestMethod.resolve(request.getMethod()); + if (requestMethod == null) { + return OperateTypeEnum.OTHER; + } + switch (requestMethod) { + case GET: + return OperateTypeEnum.GET; + case POST: + return OperateTypeEnum.CREATE; + case PUT: + return OperateTypeEnum.UPDATE; + case DELETE: + return OperateTypeEnum.DELETE; + default: + return OperateTypeEnum.OTHER; + } + } + + // ========== 请求和响应的脱敏逻辑,移除类似 password、token 等敏感字段 ========== + + private static String sanitizeMap(Map map, String[] sanitizeKeys) { + if (CollUtil.isNotEmpty(map)) { + return null; + } + if (sanitizeKeys != null) { + MapUtil.removeAny(map, sanitizeKeys); + } + MapUtil.removeAny(map, SANITIZE_KEYS); + return JsonUtils.toJsonString(map); + } + + private static String sanitizeJson(String jsonString, String[] sanitizeKeys) { + if (StrUtil.isEmpty(jsonString)) { + return null; + } + try { + JsonNode rootNode = JsonUtils.parseTree(jsonString); + sanitizeJson(rootNode, sanitizeKeys); + return JsonUtils.toJsonString(rootNode); + } catch (Exception e) { + // 脱敏失败的情况下,直接忽略异常,避免影响用户请求 + log.error("[sanitizeJson][脱敏({}) 发生异常]", jsonString, e); + return jsonString; + } + } + + private static String sanitizeJson(CommonResult commonResult, String[] sanitizeKeys) { + if (commonResult == null) { + return null; + } + String jsonString = toJsonString(commonResult); + try { + JsonNode rootNode = JsonUtils.parseTree(jsonString); + sanitizeJson(rootNode.get("data"), sanitizeKeys); // 只处理 data 字段,不处理 code、msg 字段,避免错误被脱敏掉 + return JsonUtils.toJsonString(rootNode); + } catch (Exception e) { + // 脱敏失败的情况下,直接忽略异常,避免影响用户请求 + log.error("[sanitizeJson][脱敏({}) 发生异常]", jsonString, e); + return jsonString; + } + } + + private static void sanitizeJson(JsonNode node, String[] sanitizeKeys) { + // 情况一:数组,遍历处理 + if (node.isArray()) { + for (JsonNode childNode : node) { + sanitizeJson(childNode, sanitizeKeys); + } + return; + } + // 情况二:非 Object,只是某个值,直接返回 + if (!node.isObject()) { + return; + } + // 情况三:Object,遍历处理 + Iterator> iterator = node.properties().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + if (ArrayUtil.contains(sanitizeKeys, entry.getKey()) + || ArrayUtil.contains(SANITIZE_KEYS, entry.getKey())) { + iterator.remove(); + continue; + } + sanitizeJson(entry.getValue(), sanitizeKeys); + } } } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/interceptor/ApiAccessLogInterceptor.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/interceptor/ApiAccessLogInterceptor.java new file mode 100644 index 000000000..1cd43916f --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/interceptor/ApiAccessLogInterceptor.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.framework.apilog.core.interceptor; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.common.util.spring.SpringUtils; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.StopWatch; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +import java.util.Map; + +/** + * API 访问日志 Interceptor + * + * 目的:在非 prod 环境时,打印 request 和 response 两条日志到日志文件(控制台)中。 + * + * @author 芋道源码 + */ +@Slf4j +public class ApiAccessLogInterceptor implements HandlerInterceptor { + + public static final String ATTRIBUTE_HANDLER_METHOD = "HANDLER_METHOD"; + + private static final String ATTRIBUTE_STOP_WATCH = "ApiAccessLogInterceptor.StopWatch"; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + // 记录 HandlerMethod,提供给 ApiAccessLogFilter 使用 + HandlerMethod handlerMethod = handler instanceof HandlerMethod ? (HandlerMethod) handler : null; + if (handlerMethod != null) { + request.setAttribute(ATTRIBUTE_HANDLER_METHOD, handlerMethod); + } + + // 打印 request 日志 + if (!SpringUtils.isProd()) { + Map queryString = ServletUtils.getParamMap(request); + String requestBody = ServletUtils.isJsonRequest(request) ? ServletUtils.getBody(request) : null; + if (CollUtil.isEmpty(queryString) && StrUtil.isEmpty(requestBody)) { + log.info("[preHandle][开始请求 URL({}) 无参数]", request.getRequestURI()); + } else { + log.info("[preHandle][开始请求 URL({}) 参数({})]", request.getRequestURI(), + StrUtil.nullToDefault(requestBody, queryString.toString())); + } + // 计时 + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + request.setAttribute(ATTRIBUTE_STOP_WATCH, stopWatch); + } + return true; + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { + // 打印 response 日志 + if (!SpringUtils.isProd()) { + StopWatch stopWatch = (StopWatch) request.getAttribute(ATTRIBUTE_STOP_WATCH); + stopWatch.stop(); + log.info("[afterCompletion][完成请求 URL({}) 耗时({} ms)]", + request.getRequestURI(), stopWatch.getTotalTimeMillis()); + } + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLog.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLog.java deleted file mode 100644 index 7799c42f6..000000000 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLog.java +++ /dev/null @@ -1,85 +0,0 @@ -package cn.iocoder.yudao.framework.apilog.core.service; - -import lombok.Data; - -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; - -/** - * API 访问日志 - * - * @author 芋道源码 - */ -@Data -public class ApiAccessLog { - - /** - * 链路追踪编号 - */ - private String traceId; - /** - * 用户编号 - */ - private Long userId; - /** - * 用户类型 - */ - private Integer userType; - /** - * 应用名 - */ - @NotNull(message = "应用名不能为空") - private String applicationName; - - /** - * 请求方法名 - */ - @NotNull(message = "http 请求方法不能为空") - private String requestMethod; - /** - * 访问地址 - */ - @NotNull(message = "访问地址不能为空") - private String requestUrl; - /** - * 请求参数 - */ - @NotNull(message = "请求参数不能为空") - private String requestParams; - /** - * 用户 IP - */ - @NotNull(message = "ip 不能为空") - private String userIp; - /** - * 浏览器 UA - */ - @NotNull(message = "User-Agent 不能为空") - private String userAgent; - - /** - * 开始请求时间 - */ - @NotNull(message = "开始请求时间不能为空") - private LocalDateTime beginTime; - /** - * 结束请求时间 - */ - @NotNull(message = "结束请求时间不能为空") - private LocalDateTime endTime; - /** - * 执行时长,单位:毫秒 - */ - @NotNull(message = "执行时长不能为空") - private Integer duration; - /** - * 结果码 - */ - @NotNull(message = "错误码不能为空") - private Integer resultCode; - /** - * 结果提示 - */ - private String resultMsg; - -} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkService.java index 9bfc3a573..2f3c78f60 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkService.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkService.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.framework.apilog.core.service; +import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO; + /** * API 访问日志 Framework Service 接口 * @@ -10,8 +12,8 @@ public interface ApiAccessLogFrameworkService { /** * 创建 API 访问日志 * - * @param apiAccessLog API 访问日志 + * @param reqDTO API 访问日志 */ - void createApiAccessLog(ApiAccessLog apiAccessLog); + void createApiAccessLog(ApiAccessLogCreateReqDTO reqDTO); } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkServiceImpl.java index 826897263..8f8e34306 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkServiceImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkServiceImpl.java @@ -1,7 +1,5 @@ package cn.iocoder.yudao.framework.apilog.core.service; -import cn.hutool.core.bean.BeanUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi; import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO; import lombok.RequiredArgsConstructor; @@ -10,7 +8,7 @@ import org.springframework.scheduling.annotation.Async; /** * API 访问日志 Framework Service 实现类 * - * 基于 {@link ApiAccessLogApi} 远程服务,记录访问日志 + * 基于 {@link ApiAccessLogApi} 服务,记录访问日志 * * @author 芋道源码 */ @@ -21,9 +19,8 @@ public class ApiAccessLogFrameworkServiceImpl implements ApiAccessLogFrameworkSe @Override @Async - public void createApiAccessLog(ApiAccessLog apiAccessLog) { - ApiAccessLogCreateReqDTO reqDTO = BeanUtil.copyProperties(apiAccessLog, ApiAccessLogCreateReqDTO.class); - apiAccessLogApi.createApiAccessLog(reqDTO).checkError(); + public void createApiAccessLog(ApiAccessLogCreateReqDTO reqDTO) { + apiAccessLogApi.createApiAccessLog(reqDTO); } } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLog.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLog.java deleted file mode 100644 index 087dd5d08..000000000 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLog.java +++ /dev/null @@ -1,107 +0,0 @@ -package cn.iocoder.yudao.framework.apilog.core.service; - -import lombok.Data; - -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; - -/** - * API 错误日志 - * - * @author 芋道源码 - */ -@Data -public class ApiErrorLog { - - /** - * 链路编号 - */ - private String traceId; - /** - * 账号编号 - */ - private Long userId; - /** - * 用户类型 - */ - private Integer userType; - /** - * 应用名 - */ - @NotNull(message = "应用名不能为空") - private String applicationName; - - /** - * 请求方法名 - */ - @NotNull(message = "http 请求方法不能为空") - private String requestMethod; - /** - * 访问地址 - */ - @NotNull(message = "访问地址不能为空") - private String requestUrl; - /** - * 请求参数 - */ - @NotNull(message = "请求参数不能为空") - private String requestParams; - /** - * 用户 IP - */ - @NotNull(message = "ip 不能为空") - private String userIp; - /** - * 浏览器 UA - */ - @NotNull(message = "User-Agent 不能为空") - private String userAgent; - - /** - * 异常时间 - */ - @NotNull(message = "异常时间不能为空") - private LocalDateTime exceptionTime; - /** - * 异常名 - */ - @NotNull(message = "异常名不能为空") - private String exceptionName; - /** - * 异常发生的类全名 - */ - @NotNull(message = "异常发生的类全名不能为空") - private String exceptionClassName; - /** - * 异常发生的类文件 - */ - @NotNull(message = "异常发生的类文件不能为空") - private String exceptionFileName; - /** - * 异常发生的方法名 - */ - @NotNull(message = "异常发生的方法名不能为空") - private String exceptionMethodName; - /** - * 异常发生的方法所在行 - */ - @NotNull(message = "异常发生的方法所在行不能为空") - private Integer exceptionLineNumber; - /** - * 异常的栈轨迹异常的栈轨迹 - */ - @NotNull(message = "异常的栈轨迹不能为空") - private String exceptionStackTrace; - /** - * 异常导致的根消息 - */ - @NotNull(message = "异常导致的根消息不能为空") - private String exceptionRootCauseMessage; - /** - * 异常导致的消息 - */ - @NotNull(message = "异常导致的消息不能为空") - private String exceptionMessage; - - -} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkService.java index 403c574bc..33bebb711 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkService.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkService.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.framework.apilog.core.service; +import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO; + /** * API 错误日志 Framework Service 接口 * @@ -10,8 +12,8 @@ public interface ApiErrorLogFrameworkService { /** * 创建 API 错误日志 * - * @param apiErrorLog API 错误日志 + * @param reqDTO API 错误日志 */ - void createApiErrorLog(ApiErrorLog apiErrorLog); + void createApiErrorLog(ApiErrorLogCreateReqDTO reqDTO); } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkServiceImpl.java index d400faa7f..32e4f8043 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkServiceImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkServiceImpl.java @@ -1,7 +1,5 @@ package cn.iocoder.yudao.framework.apilog.core.service; -import cn.hutool.core.bean.BeanUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi; import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO; import lombok.RequiredArgsConstructor; @@ -10,7 +8,7 @@ import org.springframework.scheduling.annotation.Async; /** * API 错误日志 Framework Service 实现类 * - * 基于 {@link ApiErrorLogApi} 远程服务,记录错误日志 + * 基于 {@link ApiErrorLogApi} 服务,记录错误日志 * * @author 芋道源码 */ @@ -21,9 +19,8 @@ public class ApiErrorLogFrameworkServiceImpl implements ApiErrorLogFrameworkServ @Override @Async - public void createApiErrorLog(ApiErrorLog apiErrorLog) { - ApiErrorLogCreateReqDTO reqDTO = BeanUtil.copyProperties(apiErrorLog, ApiErrorLogCreateReqDTO.class); - apiErrorLogApi.createApiErrorLog(reqDTO).checkError(); + public void createApiErrorLog(ApiErrorLogCreateReqDTO reqDTO) { + apiErrorLogApi.createApiErrorLog(reqDTO); } } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/core/SpringFoxHandlerProviderBeanPostProcessor.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/core/SpringFoxHandlerProviderBeanPostProcessor.java deleted file mode 100644 index 38374336a..000000000 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/core/SpringFoxHandlerProviderBeanPostProcessor.java +++ /dev/null @@ -1,42 +0,0 @@ -//package cn.iocoder.yudao.framework.swagger.core; -// -//import cn.hutool.core.util.ReflectUtil; -//import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -//import org.springframework.beans.BeansException; -//import org.springframework.beans.factory.config.BeanPostProcessor; -//import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping; -//import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider; -// -//import java.util.List; -// -///** -// * 解决 SpringFox 与 SpringBoot 2.6.x 不兼容的问题 -// * 该问题对应的 issue 为 https://github.com/springfox/springfox/issues/3462 -// * -// * @author 芋道源码 -// */ -//public class SpringFoxHandlerProviderBeanPostProcessor implements BeanPostProcessor { -// -// @Override -// public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { -// if (bean instanceof WebMvcRequestHandlerProvider) { -// customizeSpringfoxHandlerMappings(getHandlerMappings(bean)); -// } -// return bean; -// } -// -// private void customizeSpringfoxHandlerMappings(List mappings) { -// // 移除,只保留 patternParser -// List copy = CollectionUtils.filterList(mappings, mapping -> mapping.getPatternParser() == null); -// // 添加到 mappings 中 -// mappings.clear(); -// mappings.addAll(copy); -// } -// -// @SuppressWarnings("unchecked") -// private List getHandlerMappings(Object bean) { -// return (List) -// ReflectUtil.getFieldValue(bean, "handlerMappings"); -// } -// -//} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java index d3ef5f93f..bd005d2d5 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java @@ -3,8 +3,7 @@ package cn.iocoder.yudao.framework.web.core.handler; import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.servlet.ServletUtil; -import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLog; +import cn.hutool.extra.servlet.JakartaServletUtil; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; @@ -12,6 +11,7 @@ import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; +import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.AccessDeniedException; @@ -26,10 +26,10 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; import org.springframework.web.servlet.NoHandlerFoundException; -import javax.servlet.http.HttpServletRequest; -import javax.validation.ConstraintViolation; -import javax.validation.ConstraintViolationException; -import javax.validation.ValidationException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.ConstraintViolationException; +import jakarta.validation.ValidationException; import java.time.LocalDateTime; import java.util.Map; import java.util.Objects; @@ -46,6 +46,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC @Slf4j public class GlobalExceptionHandler { + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") private final String applicationName; private final ApiErrorLogFrameworkService apiErrorLogFrameworkService; @@ -230,17 +231,17 @@ public class GlobalExceptionHandler { // 情况三:处理异常 log.error("[defaultExceptionHandler]", ex); // 插入异常日志 - this.createExceptionLog(req, ex); + createExceptionLog(req, ex); // 返回 ERROR CommonResult return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg()); } private void createExceptionLog(HttpServletRequest req, Throwable e) { // 插入错误日志 - ApiErrorLog errorLog = new ApiErrorLog(); + ApiErrorLogCreateReqDTO errorLog = new ApiErrorLogCreateReqDTO(); try { // 初始化 errorLog - initExceptionLog(errorLog, req, e); + buildExceptionLog(errorLog, req, e); // 执行插入 errorLog apiErrorLogFrameworkService.createApiErrorLog(errorLog); } catch (Throwable th) { @@ -248,7 +249,7 @@ public class GlobalExceptionHandler { } } - private void initExceptionLog(ApiErrorLog errorLog, HttpServletRequest request, Throwable e) { + private void buildExceptionLog(ApiErrorLogCreateReqDTO errorLog, HttpServletRequest request, Throwable e) { // 处理用户信息 errorLog.setUserId(WebFrameworkUtils.getLoginUserId(request)); errorLog.setUserType(WebFrameworkUtils.getLoginUserType(request)); @@ -269,12 +270,12 @@ public class GlobalExceptionHandler { errorLog.setApplicationName(applicationName); errorLog.setRequestUrl(request.getRequestURI()); Map requestParams = MapUtil.builder() - .put("query", ServletUtil.getParamMap(request)) - .put("body", ServletUtil.getBody(request)).build(); + .put("query", JakartaServletUtil.getParamMap(request)) + .put("body", JakartaServletUtil.getBody(request)).build(); errorLog.setRequestParams(JsonUtils.toJsonString(requestParams)); errorLog.setRequestMethod(request.getMethod()); errorLog.setUserAgent(ServletUtils.getUserAgent(request)); - errorLog.setUserIp(ServletUtil.getClientIP(request)); + errorLog.setUserIp(JakartaServletUtil.getClientIP(request)); errorLog.setExceptionTime(LocalDateTime.now()); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/application.yaml b/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/application.yaml index 8e3069139..da4749c57 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/application.yaml +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/application.yaml @@ -81,6 +81,11 @@ spring: repositories: enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度 +# VO 转换(数据翻译)相关 +easy-trans: + is-enable-global: true # 启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口 + is-enable-cloud: false # 禁用 TransType.RPC 微服务模式 + --- #################### RPC 远程调用相关配置 #################### --- #################### MQ 消息队列相关配置 #################### diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/application.yaml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/application.yaml index dcbd00cda..25fc265a0 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/application.yaml +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/application.yaml @@ -70,6 +70,11 @@ spring: repositories: enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度 +# VO 转换(数据翻译)相关 +easy-trans: + is-enable-global: true # 启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口 + is-enable-cloud: false # 禁用 TransType.RPC 微服务模式 + --- #################### MQ 消息队列相关配置 #################### --- #################### 定时任务相关配置 #################### diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/dto/ApiAccessLogCreateReqDTO.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/dto/ApiAccessLogCreateReqDTO.java index 40102ea32..2e7c4298c 100644 --- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/dto/ApiAccessLogCreateReqDTO.java +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/dto/ApiAccessLogCreateReqDTO.java @@ -27,9 +27,10 @@ public class ApiAccessLogCreateReqDTO { @Schema(description = "请求地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "/xxx/yyy") @NotNull(message = "访问地址不能为空") private String requestUrl; - @Schema(description = "请求参数", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "请求参数不能为空") + @Schema(description = "请求参数") private String requestParams; + @Schema(description = "响应结果") + private String responseBody; @Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1") @NotNull(message = "ip 不能为空") private String userIp; @@ -37,6 +38,13 @@ public class ApiAccessLogCreateReqDTO { @NotNull(message = "User-Agent 不能为空") private String userAgent; + @Schema(description = "操作模块", requiredMode = Schema.RequiredMode.REQUIRED, example = "商品模块") + private String operateModule; + @Schema(description = "操作名", requiredMode = Schema.RequiredMode.REQUIRED, example = "商品新增") + private String operateName; + @Schema(description = "操作分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer operateType; // 参见 OperateTypeEnum 枚举 + @Schema(description = "开始时间",requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "开始请求时间不能为空") private LocalDateTime beginTime; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java index 5e3f3c976..ff0fed7a3 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java @@ -48,6 +48,10 @@ public class ApiAccessLogRespVO { @ExcelProperty("请求参数") private String requestParams; + @Schema(description = "响应结果") + @ExcelProperty("响应结果") + private String responseBody; + @Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1") @ExcelProperty("用户 IP") private String userIp; @@ -56,6 +60,19 @@ public class ApiAccessLogRespVO { @ExcelProperty("浏览器 UA") private String userAgent; + @Schema(description = "操作模块", requiredMode = Schema.RequiredMode.REQUIRED, example = "商品模块") + @ExcelProperty("操作模块") + private String operateModule; + + @Schema(description = "操作名", requiredMode = Schema.RequiredMode.REQUIRED, example = "创建商品") + @ExcelProperty("操作名") + private String operateName; + + @Schema(description = "操作分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "操作分类", converter = DictConvert.class) + @DictFormat(DictTypeConstants.OPERATE_TYPE) + private Integer operateType; + @Schema(description = "开始请求时间", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("开始请求时间") private LocalDateTime beginTime; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/logger/ApiAccessLogDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/logger/ApiAccessLogDO.java index ab4292bf9..d4850fcc8 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/logger/ApiAccessLogDO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/logger/ApiAccessLogDO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.infra.dal.dataobject.logger; +import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; @@ -70,6 +71,10 @@ public class ApiAccessLogDO extends BaseDO { * body: Quest Body */ private String requestParams; + /** + * 响应结果 + */ + private String responseBody; /** * 用户 IP */ @@ -81,6 +86,21 @@ public class ApiAccessLogDO extends BaseDO { // ========== 执行相关字段 ========== + /** + * 操作模块 + */ + private String operateModule; + /** + * 操作名 + */ + private String operateName; + /** + * 操作分类 + * + * 枚举 {@link OperateTypeEnum} + */ + private Integer operateType; + /** * 开始请求时间 */ @@ -93,6 +113,7 @@ public class ApiAccessLogDO extends BaseDO { * 执行时长,单位:毫秒 */ private Integer duration; + /** * 结果码 * diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application.yaml b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application.yaml index dea79c8be..2ca2a28c5 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application.yaml +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application.yaml @@ -70,6 +70,11 @@ spring: repositories: enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度 +# VO 转换(数据翻译)相关 +easy-trans: + is-enable-global: true # 启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口 + is-enable-cloud: false # 禁用 TransType.RPC 微服务模式 + --- #################### RPC 远程调用相关配置 #################### --- #################### 消息队列相关 #################### diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/create_tables.sql b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/create_tables.sql index a5f896ce1..9f383ac5a 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/create_tables.sql @@ -94,8 +94,12 @@ CREATE TABLE IF NOT EXISTS "infra_api_access_log" ( "request_method" varchar(16) not null default '', "request_url" varchar(255) not null default '', "request_params" varchar(8000) not null default '', + "response_body" varchar(8000) not null default '', "user_ip" varchar(50) not null, "user_agent" varchar(512) not null, + `operate_module` varchar(50) NOT NULL, + `operate_name` varchar(50) NOT NULL, + `operate_type` bigint(4) NOT NULL DEFAULT '0', "begin_time" timestamp not null, "end_time" timestamp not null, "duration" integer not null, @@ -108,7 +112,7 @@ CREATE TABLE IF NOT EXISTS "infra_api_access_log" ( "deleted" bit not null default false, "tenant_id" bigint not null default '0', primary key ("id") - ) COMMENT 'API 访问日志表'; +) COMMENT 'API 访问日志表'; CREATE TABLE IF NOT EXISTS "infra_api_error_log" ( "id" bigint not null GENERATED BY DEFAULT AS IDENTITY, diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/resources/application.yaml b/yudao-module-mall/yudao-module-product-biz/src/main/resources/application.yaml index 75088bc0a..9380dd226 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/resources/application.yaml +++ b/yudao-module-mall/yudao-module-product-biz/src/main/resources/application.yaml @@ -70,6 +70,11 @@ spring: repositories: enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度 +# VO 转换(数据翻译)相关 +easy-trans: + is-enable-global: true # 启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口 + is-enable-cloud: false # 禁用 TransType.RPC 微服务模式 + --- #################### RPC 远程调用相关配置 #################### --- #################### MQ 消息队列相关配置 #################### diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/resources/application.yaml b/yudao-module-mall/yudao-module-promotion-biz/src/main/resources/application.yaml index 4fdf33e00..5cef5b381 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/resources/application.yaml +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/resources/application.yaml @@ -70,6 +70,11 @@ spring: repositories: enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度 +# VO 转换(数据翻译)相关 +easy-trans: + is-enable-global: true # 启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口 + is-enable-cloud: false # 禁用 TransType.RPC 微服务模式 + --- #################### RPC 远程调用相关配置 #################### --- #################### MQ 消息队列相关配置 #################### diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/application.yaml b/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/application.yaml index bbb22b999..9c38b215f 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/application.yaml +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/application.yaml @@ -70,6 +70,11 @@ spring: repositories: enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度 +# VO 转换(数据翻译)相关 +easy-trans: + is-enable-global: true # 启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口 + is-enable-cloud: false # 禁用 TransType.RPC 微服务模式 + --- #################### RPC 远程调用相关配置 #################### --- #################### MQ 消息队列相关配置 #################### diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/resources/application.yaml b/yudao-module-mall/yudao-module-trade-biz/src/main/resources/application.yaml index 1ad9394e0..7e72ac59d 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/resources/application.yaml +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/resources/application.yaml @@ -70,6 +70,11 @@ spring: repositories: enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度 +# VO 转换(数据翻译)相关 +easy-trans: + is-enable-global: true # 启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口 + is-enable-cloud: false # 禁用 TransType.RPC 微服务模式 + --- #################### RPC 远程调用相关配置 #################### --- #################### MQ 消息队列相关配置 #################### diff --git a/yudao-module-member/yudao-module-member-biz/src/main/resources/application.yaml b/yudao-module-member/yudao-module-member-biz/src/main/resources/application.yaml index 9a5bc0937..50bfa4e28 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/resources/application.yaml +++ b/yudao-module-member/yudao-module-member-biz/src/main/resources/application.yaml @@ -70,6 +70,11 @@ spring: repositories: enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度 +# VO 转换(数据翻译)相关 +easy-trans: + is-enable-global: true # 启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口 + is-enable-cloud: false # 禁用 TransType.RPC 微服务模式 + --- #################### RPC 远程调用相关配置 #################### --- #################### MQ 消息队列相关配置 #################### diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/resources/application.yaml b/yudao-module-mp/yudao-module-mp-biz/src/main/resources/application.yaml index d66716b3b..17678a342 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/resources/application.yaml +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/resources/application.yaml @@ -70,6 +70,11 @@ spring: repositories: enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度 +# VO 转换(数据翻译)相关 +easy-trans: + is-enable-global: true # 启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口 + is-enable-cloud: false # 禁用 TransType.RPC 微服务模式 + --- #################### MQ 消息队列相关配置 #################### --- #################### 定时任务相关配置 #################### diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/resources/application.yaml b/yudao-module-pay/yudao-module-pay-biz/src/main/resources/application.yaml index 599e71d12..549908019 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/resources/application.yaml +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/resources/application.yaml @@ -70,6 +70,11 @@ spring: repositories: enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度 +# VO 转换(数据翻译)相关 +easy-trans: + is-enable-global: true # 启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口 + is-enable-cloud: false # 禁用 TransType.RPC 微服务模式 + --- #################### MQ 消息队列相关配置 #################### --- #################### 定时任务相关配置 #################### diff --git a/yudao-module-report/yudao-module-report-biz/src/main/resources/application.yaml b/yudao-module-report/yudao-module-report-biz/src/main/resources/application.yaml index dbc2279a0..35771dbfa 100644 --- a/yudao-module-report/yudao-module-report-biz/src/main/resources/application.yaml +++ b/yudao-module-report/yudao-module-report-biz/src/main/resources/application.yaml @@ -70,6 +70,11 @@ spring: repositories: enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度 +# VO 转换(数据翻译)相关 +easy-trans: + is-enable-global: true # 启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口 + is-enable-cloud: false # 禁用 TransType.RPC 微服务模式 + --- #################### RPC 远程调用相关配置 #################### --- #################### MQ 消息队列相关配置 #################### diff --git a/yudao-module-report/yudao-module-report-biz/src/test/resources/sql/create_tables.sql b/yudao-module-report/yudao-module-report-biz/src/test/resources/sql/create_tables.sql index 2ad39015d..a77397fea 100644 --- a/yudao-module-report/yudao-module-report-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-report/yudao-module-report-biz/src/test/resources/sql/create_tables.sql @@ -11,4 +11,4 @@ CREATE TABLE IF NOT EXISTS "report_go_view_project" ( "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, "deleted" bit NOT NULL DEFAULT FALSE, PRIMARY KEY ("id") -) COMMENT 'GoView 项目表'; \ No newline at end of file +) COMMENT 'GoView 项目表'; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/NotifyMessageController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/NotifyMessageController.java index 93394ddbb..d311a6316 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/NotifyMessageController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/NotifyMessageController.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.system.controller.admin.notify; +import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -88,6 +89,7 @@ public class NotifyMessageController { @GetMapping("/get-unread-count") @Operation(summary = "获得当前用户的未读站内信数量") + @ApiAccessLog(enable = false) // 由于前端会不断轮询该接口,记录日志没有意义 public CommonResult getUnreadNotifyMessageCount() { return success(notifyMessageService.getUnreadNotifyMessageCount( getLoginUserId(), UserTypeEnum.ADMIN.getValue()));