Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cb 5440 merge into internal db #2914

Open
wants to merge 23 commits into
base: devel
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c7c2da6
CB-5440. Init commit
DenisSinelnikov Sep 12, 2024
8f832cc
CB-5440. Move logic to abstract class
DenisSinelnikov Sep 12, 2024
1793b9a
CB-4095. Refactor after review, added sub group for envs
DenisSinelnikov Sep 13, 2024
faca96d
Merge branch 'devel' into CB-5440-merge-into-internal-db
DenisSinelnikov Sep 13, 2024
27598cf
CB-4095. Fix build, add some refactoring, fix export package
DenisSinelnikov Sep 13, 2024
f25ada3
Merge branch 'devel' into CB-5440-merge-into-internal-db
DenisSinelnikov Sep 18, 2024
1a660cf
Merge branch 'devel' into CB-5440-merge-into-internal-db
DenisSinelnikov Sep 18, 2024
a4656a2
Merge remote-tracking branch 'origin/CB-5440-merge-into-internal-db' …
DenisSinelnikov Sep 18, 2024
19dd574
CB-5440. Refactor after review
DenisSinelnikov Sep 19, 2024
3fcaf75
CB-5440. Move more logic to InternalDB
DenisSinelnikov Sep 19, 2024
203c325
Merge branch 'devel' into CB-5440-merge-into-internal-db
DenisSinelnikov Sep 19, 2024
b1301d9
CB-5440. Move more logic to InternalDB
DenisSinelnikov Sep 19, 2024
b527fdd
Merge remote-tracking branch 'origin/CB-5440-merge-into-internal-db' …
DenisSinelnikov Sep 19, 2024
3102be4
Merge branch 'devel' into CB-5440-merge-into-internal-db
DenisSinelnikov Dec 2, 2024
68361a7
CB-5440. Resolve conflicts
DenisSinelnikov Dec 5, 2024
bd73f2c
Merge branch 'devel' into CB-5440-merge-into-internal-db
DenisSinelnikov Dec 5, 2024
952e3a9
Merge branch 'devel' into CB-5440-merge-into-internal-db
mr-anton-t Dec 6, 2024
7af78a9
CB-5440. Fixed update schema if schema exist
DenisSinelnikov Dec 10, 2024
4df1fd4
Merge branch 'devel' into CB-5440-merge-into-internal-db
mr-anton-t Dec 11, 2024
0161971
Merge branch 'devel' into CB-5440-merge-into-internal-db
dariamarutkina Dec 12, 2024
18972ad
Merge branch 'devel' into CB-5440-merge-into-internal-db
dariamarutkina Dec 13, 2024
02691dc
CB-5440. Merge devel
DenisSinelnikov Dec 17, 2024
7035c7c
Merge branch 'devel' into CB-5440-merge-into-internal-db
DenisSinelnikov Dec 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ Require-Bundle: org.jkiss.dbeaver.model;visibility:=reexport,
org.jkiss.dbeaver.model.sql.jdbc,
org.jkiss.dbeaver.registry;visibility:=reexport,
org.jkiss.bundle.apache.dbcp;visibility:=reexport,
io.cloudbeaver.model
io.cloudbeaver.model,
org.jkiss.dbeaver.db.internal;visibility:=reexport
Export-Package: io.cloudbeaver.auth.provider.local,
io.cloudbeaver.auth.provider.rp,
io.cloudbeaver.service.security,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3122,11 +3122,11 @@
}
}

public void shutdown() {

Check warning on line 3125 in server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java

View workflow job for this annotation

GitHub Actions / Server / Lint

[checkstyle] reported by reviewdog 🐶 Missing a Javadoc comment. Raw Output: /github/workspace/./server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java:3125:5: warning: Missing a Javadoc comment. (com.puppycrawl.tools.checkstyle.checks.javadoc.MissingJavadocMethodCheck)
database.shutdown();
database.closeConnection();
}

public void finishConfiguration(

Check warning on line 3129 in server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java

View workflow job for this annotation

GitHub Actions / Server / Lint

[checkstyle] reported by reviewdog 🐶 Missing a Javadoc comment. Raw Output: /github/workspace/./server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java:3129:5: warning: Missing a Javadoc comment. (com.puppycrawl.tools.checkstyle.checks.javadoc.MissingJavadocMethodCheck)
@NotNull String adminName,
@Nullable String adminPassword,
@NotNull List<AuthInfo> authInfoList
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ application, database, new NoAuthCredentialsProvider(), smConfig
try {
database.initialize();
} catch (DBException e) {
database.shutdown();
database.closeConnection();
throw e;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,11 @@
import io.cloudbeaver.registry.WebAuthProviderRegistry;
import io.cloudbeaver.utils.ServletAppUtils;
import org.apache.commons.dbcp2.*;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.db.internal.InternalDB;
import org.jkiss.dbeaver.model.DBConstants;
import org.jkiss.dbeaver.model.auth.AuthInfo;
import org.jkiss.dbeaver.model.connection.DBPDriver;
Expand All @@ -43,24 +42,16 @@
import org.jkiss.dbeaver.model.security.SMAdminController;
import org.jkiss.dbeaver.model.security.user.SMTeam;
import org.jkiss.dbeaver.model.security.user.SMUser;
import org.jkiss.dbeaver.model.sql.SQLDialect;
import org.jkiss.dbeaver.model.sql.SQLDialectSchemaController;
import org.jkiss.dbeaver.model.sql.schema.ClassLoaderScriptSource;
import org.jkiss.dbeaver.model.sql.schema.SQLSchemaManager;
import org.jkiss.dbeaver.model.sql.schema.SQLSchemaVersionManager;
import org.jkiss.dbeaver.registry.DataSourceProviderRegistry;
import org.jkiss.dbeaver.registry.storage.H2Migrator;
import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.dbeaver.utils.GeneralUtils;
import org.jkiss.dbeaver.utils.RuntimeUtils;
import org.jkiss.dbeaver.utils.SystemVariablesResolver;
import org.jkiss.utils.CommonUtils;
import org.jkiss.utils.IOUtils;
import org.jkiss.utils.SecurityUtils;

import java.io.*;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.util.*;
Expand All @@ -69,7 +60,7 @@
/**
* Database management
*/
public class CBDatabase {
public class CBDatabase extends InternalDB {
private static final Log log = Log.getLog(CBDatabase.class);

public static final String SCHEMA_CREATE_SQL_PATH = "db/cb_schema_create.sql";
Expand All @@ -82,17 +73,19 @@
private static final String DEFAULT_DB_PWD_FILE = ".database-credentials.dat";
private static final String V1_DB_NAME = "cb.h2.dat";
private static final String V2_DB_NAME = "cb.h2v2.dat";
public static final String CB_SCHEMA_INFO_TABLE_NAME = "CB_SCHEMA_INFO";
private static final String MAC_ADDRESS = "macAddress";
private static final String HOST_NAME = "hostName";

private final ServletApplication application;
private final WebDatabaseConfig databaseConfiguration;
private PoolingDataSource<PoolableConnection> cbDataSource;
private transient volatile Connection exclusiveConnection;

private String instanceId;
private SMAdminController adminSecurityController;
private SQLDialect dialect;

public CBDatabase(ServletApplication application, WebDatabaseConfig databaseConfiguration) {
super(databaseConfiguration, application);
this.application = application;
this.databaseConfiguration = databaseConfiguration;
}
Expand All @@ -109,25 +102,18 @@
if (exclusiveConnection != null) {
return exclusiveConnection;
}
return cbDataSource.getConnection();
}

public PoolingDataSource<PoolableConnection> getConnectionPool() {
return cbDataSource;
return getDbConnection().getConnection();
}

public void initialize() throws DBException {

Check warning on line 108 in server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabase.java

View workflow job for this annotation

GitHub Actions / Server / Lint

[checkstyle] reported by reviewdog 🐶 Missing a Javadoc comment. Raw Output: /github/workspace/./server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabase.java:108:5: warning: Missing a Javadoc comment. (com.puppycrawl.tools.checkstyle.checks.javadoc.MissingJavadocMethodCheck)
log.debug("Initiate management database");
if (CommonUtils.isEmpty(databaseConfiguration.getDriver())) {
throw new DBException("No database driver configured for CloudBeaver database");
}
var dataSourceProviderRegistry = DataSourceProviderRegistry.getInstance();
DBPDriver driver = dataSourceProviderRegistry.findDriver(databaseConfiguration.getDriver());
if (driver == null) {
throw new DBException("Driver '" + databaseConfiguration.getDriver() + "' not found");
}
var dataSourceProviderRegistry = getDataSourceProviderRegistry();
DBPDriver driver = findDriver(dataSourceProviderRegistry);

LoggingProgressMonitor monitor = new LoggingProgressMonitor(log);

Check warning on line 116 in server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabase.java

View workflow job for this annotation

GitHub Actions / Server / Lint

[checkstyle] reported by reviewdog 🐶 Distance between variable 'monitor' declaration and its first usage is 4, but allowed 3. Consider making that variable final if you still need to store its value in advance (before method calls that might have side effects on the original value). Raw Output: /github/workspace/./server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabase.java:116:9: warning: Distance between variable 'monitor' declaration and its first usage is 4, but allowed 3. Consider making that variable final if you still need to store its value in advance (before method calls that might have side effects on the original value). (com.puppycrawl.tools.checkstyle.checks.coding.VariableDeclarationUsageDistanceCheck)

if (isDefaultH2Configuration(databaseConfiguration)) {
//force use default values even if they are explicitly specified
Expand Down Expand Up @@ -165,7 +151,7 @@
}
}

String dbURL = GeneralUtils.replaceVariables(databaseConfiguration.getUrl(), SystemVariablesResolver.INSTANCE);
String dbURL = getDbURL();
Properties dbProperties = new Properties();
if (!CommonUtils.isEmpty(dbUser)) {
dbProperties.put(DBConstants.DATA_SOURCE_PROPERTY_USER, dbUser);
Expand All @@ -184,37 +170,26 @@
}

// reload the driver and url due to a possible configuration update
driver = dataSourceProviderRegistry.findDriver(databaseConfiguration.getDriver());
driver = findDriver(dataSourceProviderRegistry);
if (driver == null) {
throw new DBException("Driver '" + databaseConfiguration.getDriver() + "' not found");
}
Driver driverInstance = driver.getDriverInstance(monitor);
dbURL = GeneralUtils.replaceVariables(databaseConfiguration.getUrl(), SystemVariablesResolver.INSTANCE);
Driver driverInstance = getDriverInstance(driver, monitor);
dbURL = getDbURL();

try {
this.cbDataSource = initConnectionPool(driver, dbURL, dbProperties, driverInstance);
super.setDbConnection(initConnectionPool(driver, dbURL, dbProperties, driverInstance));
} catch (SQLException e) {
throw new DBException("Error initializing connection pool");
}
dialect = driver.getScriptDialect().createInstance();

try (Connection connection = cbDataSource.getConnection()) {
try (Connection connection = getDbConnection().getConnection()) {
DatabaseMetaData metaData = connection.getMetaData();
log.debug("\tConnected to " + metaData.getDatabaseProductName() + " " + metaData.getDatabaseProductVersion());

if (dialect instanceof SQLDialectSchemaController && CommonUtils.isNotEmpty(schemaName)) {
var dialectSchemaController = (SQLDialectSchemaController) dialect;
var schemaExistQuery = dialectSchemaController.getSchemaExistQuery(schemaName);
boolean schemaExist = JDBCUtils.executeQuery(connection, schemaExistQuery) != null;
if (!schemaExist) {
log.info("Schema " + schemaName + " not exist, create new one");
String createSchemaQuery = dialectSchemaController.getCreateSchemaQuery(
schemaName
);
JDBCUtils.executeStatement(connection, createSchemaQuery);
}
}
SQLSchemaManager schemaManager = new SQLSchemaManager(
createSchema(driver, schemaName, connection);

updateSchema(
"CB",
new ClassLoaderScriptSource(
CBDatabase.class.getClassLoader(),
Expand All @@ -223,14 +198,14 @@
),
monitor1 -> connection,
new CBSchemaVersionManager(),
dialect,
getDialect(),
null,
schemaName,
CURRENT_SCHEMA_VERSION,
0,
databaseConfiguration
databaseConfiguration,
monitor
);
schemaManager.updateSchema(monitor);

validateInstancePersistentState(connection);
} catch (Exception e) {
Expand All @@ -239,29 +214,8 @@
log.debug("\tManagement database connection established");
}

protected PoolingDataSource<PoolableConnection> initConnectionPool(
DBPDriver driver,
String dbURL,
Properties dbProperties,
Driver driverInstance
) throws SQLException, DBException {
// Create connection pool with custom connection factory
log.debug("\tInitiate connection pool with management database (" + driver.getFullName() + "; " + dbURL + ")");
DriverConnectionFactory conFactory = new DriverConnectionFactory(driverInstance, dbURL, dbProperties);
PoolableConnectionFactory pcf = new PoolableConnectionFactory(conFactory, null);
pcf.setValidationQuery(databaseConfiguration.getPool().getValidationQuery());

GenericObjectPoolConfig<PoolableConnection> config = new GenericObjectPoolConfig<>();
config.setMinIdle(databaseConfiguration.getPool().getMinIdleConnections());
config.setMaxIdle(databaseConfiguration.getPool().getMaxIdleConnections());
config.setMaxTotal(databaseConfiguration.getPool().getMaxConnections());
GenericObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(pcf, config);
pcf.setPool(connectionPool);
return new PoolingDataSource<>(connectionPool);
}

//TODO move out
public void finishConfiguration(

Check warning on line 218 in server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabase.java

View workflow job for this annotation

GitHub Actions / Server / Lint

[checkstyle] reported by reviewdog 🐶 Missing a Javadoc comment. Raw Output: /github/workspace/./server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabase.java:218:5: warning: Missing a Javadoc comment. (com.puppycrawl.tools.checkstyle.checks.javadoc.MissingJavadocMethodCheck)
@NotNull String adminName,
@Nullable String adminPassword,
@NotNull List<AuthInfo> authInfoList
Expand Down Expand Up @@ -355,27 +309,13 @@
userId);
}

public void shutdown() {
log.debug("Shutdown database");
if (cbDataSource != null) {
try {
cbDataSource.close();
} catch (SQLException e) {
log.error(e);
}
}
}

private class CBSchemaVersionManager implements SQLSchemaVersionManager {

@Override
public int getCurrentSchemaVersion(DBRProgressMonitor monitor, Connection connection, String schemaName)
throws DBException, SQLException {
public int getCurrentSchemaVersion(DBRProgressMonitor monitor, Connection connection, String schemaName) {
// Check and update schema
try {
int version = CommonUtils.toInt(JDBCUtils.executeQuery(connection,
normalizeTableNames("SELECT VERSION FROM {table_prefix}CB_SCHEMA_INFO")));
return version == 0 ? 1 : version;
return getVersionFromSchema(connection, "CB_SCHEMA_INFO", schemaName);
} catch (SQLException e) {
try {
Object legacyVersion = CommonUtils.toInt(JDBCUtils.executeQuery(connection,
Expand All @@ -400,20 +340,8 @@
@NotNull Connection connection,
@NotNull String schemaName,
int version
) throws DBException, SQLException {
var updateCount = JDBCUtils.executeUpdate(
connection,
normalizeTableNames("UPDATE {table_prefix}CB_SCHEMA_INFO SET VERSION=?,UPDATE_TIME=CURRENT_TIMESTAMP"),
version
);
if (updateCount <= 0) {
JDBCUtils.executeSQL(
connection,
normalizeTableNames(
"INSERT INTO {table_prefix}CB_SCHEMA_INFO (VERSION,UPDATE_TIME) VALUES(?,CURRENT_TIMESTAMP)"),
version
);
}
) throws SQLException {
upsertSchemaInfo(connection, CB_SCHEMA_INFO_TABLE_NAME, schemaName, version);
}

@Override
Expand Down Expand Up @@ -496,15 +424,7 @@
}

private void checkInstanceRecord(Connection connection) throws SQLException, IOException {
String hostName;
try {
hostName = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
hostName = "localhost";
}

byte[] hardwareAddress = RuntimeUtils.getLocalMacAddress();
String macAddress = CommonUtils.toHexString(hardwareAddress);
Map<String, String> hostInfo = getHostInfo();

instanceId = getCurrentInstanceId();

Expand All @@ -521,8 +441,8 @@
"(INSTANCE_ID,MAC_ADDRESS,HOST_NAME,PRODUCT_NAME,PRODUCT_VERSION,UPDATE_TIME)" +
" VALUES(?,?,?,?,?,CURRENT_TIMESTAMP)"),
instanceId,
macAddress,
hostName,
hostInfo.get(MAC_ADDRESS),
hostInfo.get(HOST_NAME),
productName,
versionName);
} else {
Expand All @@ -531,7 +451,7 @@
normalizeTableNames("UPDATE {table_prefix}CB_INSTANCE " +
"SET HOST_NAME=?,PRODUCT_NAME=?,PRODUCT_VERSION=?,UPDATE_TIME=CURRENT_TIMESTAMP " +
"WHERE INSTANCE_ID=?"),
hostName,
hostInfo.get(HOST_NAME),
productName,
versionName,
instanceId);
Expand Down Expand Up @@ -561,36 +481,7 @@
}
}

private String getCurrentInstanceId() throws IOException {
// 16 chars - workspace ID
String workspaceId = DBWorkbench.getPlatform().getWorkspace().getWorkspaceId();
if (workspaceId.length() > 16) {
workspaceId = workspaceId.substring(0, 16);
}

StringBuilder id = new StringBuilder(36);
id.append("000000000000"); // there was mac address, but it generates dynamically when docker is used
id.append(":").append(workspaceId).append(":");
while (id.length() < 36) {
id.append("X");
}
return id.toString();
}

/**
* Replaces all predefined prefixes in sql query.
*/
@NotNull
public String normalizeTableNames(@NotNull String sql) {
return CommonUtils.normalizeTableNames(sql, databaseConfiguration.getSchema());
}

@NotNull
public SQLDialect getDialect() {
return dialect;
}

public static boolean isDefaultH2Configuration(WebDatabaseConfig databaseConfiguration) {

Check warning on line 484 in server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabase.java

View workflow job for this annotation

GitHub Actions / Server / Lint

[checkstyle] reported by reviewdog 🐶 Missing a Javadoc comment. Raw Output: /github/workspace/./server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/db/CBDatabase.java:484:5: warning: Missing a Javadoc comment. (com.puppycrawl.tools.checkstyle.checks.javadoc.MissingJavadocMethodCheck)
var workspace = ServletAppUtils.getServletApplication().getWorkspaceDirectory();
var v1Path = workspace.resolve(".data").resolve(V1_DB_NAME);
var v2Path = workspace.resolve(".data").resolve(V2_DB_NAME);
Expand All @@ -611,4 +502,20 @@
protected SMAdminController getAdminSecurityController() {
return adminSecurityController;
}

protected String getCurrentInstanceId() {
// 16 chars - workspace ID
String workspaceId = DBWorkbench.getPlatform().getWorkspace().getWorkspaceId();
if (workspaceId.length() > 16) {
workspaceId = workspaceId.substring(0, 16);
}

StringBuilder id = new StringBuilder(36);
id.append("000000000000"); // there was mac address, but it generates dynamically when docker is used
id.append(":").append(workspaceId).append(":");
while (id.length() < 36) {
id.append("X");
}
return id.toString();
}
}
Loading