From e135ac680cf4946d0240608ff235bc604f7e9e86 Mon Sep 17 00:00:00 2001 From: Ruslan Date: Wed, 15 Apr 2026 19:15:52 +0200 Subject: [PATCH 1/4] dbeaver/pro#8234 only admin can overwrite existing udbt handler --- .../bundles/io.cloudbeaver.model/plugin.xml | 2 + ...eaver.rmDataSourceConfigUpdateHandler.exsd | 11 ++++ .../rm/local/BaseLocalResourceController.java | 51 +++++++++------ .../rm/local/LocalResourceController.java | 30 +++++++++ .../RMDataSourceConfigUpdateHandler.java | 32 ++++++++++ ...taSourceConfigUpdateHandlerDescriptor.java | 37 +++++++++++ ...ataSourceConfigUpdateHandlersRegistry.java | 62 +++++++++++++++++++ 7 files changed, 207 insertions(+), 18 deletions(-) create mode 100644 server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.rmDataSourceConfigUpdateHandler.exsd create mode 100644 server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandler.java create mode 100644 server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlerDescriptor.java create mode 100644 server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlersRegistry.java diff --git a/server/bundles/io.cloudbeaver.model/plugin.xml b/server/bundles/io.cloudbeaver.model/plugin.xml index de60a463385..01d919d5489 100644 --- a/server/bundles/io.cloudbeaver.model/plugin.xml +++ b/server/bundles/io.cloudbeaver.model/plugin.xml @@ -10,6 +10,8 @@ + diff --git a/server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.rmDataSourceConfigUpdateHandler.exsd b/server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.rmDataSourceConfigUpdateHandler.exsd new file mode 100644 index 00000000000..cfa43cbee72 --- /dev/null +++ b/server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.rmDataSourceConfigUpdateHandler.exsd @@ -0,0 +1,11 @@ + + + + + + + + RM data source config update handler + + + diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/BaseLocalResourceController.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/BaseLocalResourceController.java index 3ec793dceba..c1b720568cb 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/BaseLocalResourceController.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/BaseLocalResourceController.java @@ -116,22 +116,7 @@ public String getProjectsDataSources(@NotNull String projectId, @Nullable String return doFileReadOperation( projectId, projectMetadata.getMetadataFolder(false), - () -> { - DBPDataSourceRegistry registry = projectMetadata.getDataSourceRegistry(); - registry.refreshConfig(); - registry.checkForErrors(); - DataSourceConfigurationManagerBuffer buffer = new DataSourceConfigurationManagerBuffer(); - Predicate filter = null; - if (!ArrayUtils.isEmpty(dataSourceIds)) { - filter = ds -> ArrayUtils.contains(dataSourceIds, ds.getId()); - } - ((DataSourcePersistentRegistry) registry).saveConfigurationToManager(new VoidProgressMonitor(), - buffer, - filter); - registry.checkForErrors(); - - return new String(buffer.getData(), StandardCharsets.UTF_8); - } + () -> serializeProjectDataSourcesConfiguration(projectMetadata, dataSourceIds) ); } @@ -160,12 +145,13 @@ protected DataSourceParseResults updateProjectDataSourcesConfig( @Nullable List dataSourceIds ) throws DBException { try (var ignoredLock = lockController.lock(LockTarget.of(projectId), LockOptions.of("updateProjectDataSources"))) { - DBPProject project = getWebProject(projectId, false); + RMLocalProject project = getWebProject(projectId, false); + String processedConfiguration = preprocessDataSourceConfigurationUpdate(project, projectId, configuration, dataSourceIds); return doFileWriteOperation( projectId, project.getMetadataFolder(false), () -> { DBPDataSourceRegistry registry = project.getDataSourceRegistry(); - DBPDataSourceConfigurationStorage storage = new DataSourceMemoryStorage(configuration.getBytes( + DBPDataSourceConfigurationStorage storage = new DataSourceMemoryStorage(processedConfiguration.getBytes( StandardCharsets.UTF_8)); DataSourceConfigurationManager manager = new DataSourceConfigurationManagerBuffer(); final DataSourceParseResults parseResults = ((DataSourcePersistentRegistry) registry).loadDataSources( @@ -185,6 +171,35 @@ protected DataSourceParseResults updateProjectDataSourcesConfig( } } + @NotNull + protected String preprocessDataSourceConfigurationUpdate( + @NotNull RMLocalProject project, + @NotNull String projectId, + @NotNull String configuration, + @Nullable List dataSourceIds + ) throws DBException { + return configuration; + } + + @NotNull + protected String serializeProjectDataSourcesConfiguration( + @NotNull DBPProject project, + @Nullable String[] dataSourceIds + ) throws DBException { + DBPDataSourceRegistry registry = project.getDataSourceRegistry(); + registry.refreshConfig(); + registry.checkForErrors(); + DataSourceConfigurationManagerBuffer buffer = new DataSourceConfigurationManagerBuffer(); + Predicate filter = null; + if (!ArrayUtils.isEmpty(dataSourceIds)) { + filter = ds -> ArrayUtils.contains(dataSourceIds, ds.getId()); + } + ((DataSourcePersistentRegistry) registry).saveConfigurationToManager(new VoidProgressMonitor(), buffer, filter); + registry.checkForErrors(); + + return new String(buffer.getData(), StandardCharsets.UTF_8); + } + @Override public void deleteProjectDataSources( @NotNull String projectId, diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/LocalResourceController.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/LocalResourceController.java index 5a0033c300d..345ed6a5f1d 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/LocalResourceController.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/LocalResourceController.java @@ -82,6 +82,7 @@ public class LocalResourceController extends BaseLocalResourceController { private final String globalProjectName; private Supplier smControllerSupplier; protected final List fileHandlers; + protected final List dataSourceConfigUpdateHandlers; private final Map projectRegistries = new LinkedHashMap<>(); private final ProjectsMetadataInfo sharedProjectsMetadataInfo; @@ -104,6 +105,7 @@ public LocalResourceController( this.globalProjectName = DBWorkbench.getPlatform().getApplication().getDefaultProjectName(); this.fileHandlers = RMFileOperationHandlersRegistry.getInstance().getFileHandlers(); + this.dataSourceConfigUpdateHandlers = RMDataSourceConfigUpdateHandlersRegistry.getInstance().getHandlers(); this.sharedProjectsMetadataInfo = new ProjectsMetadataInfo(sharedProjectsPath, lockController); } @@ -411,6 +413,34 @@ public boolean updateProjectDataSources( return parseResults != null; } + @Override + @NotNull + protected String preprocessDataSourceConfigurationUpdate( + @NotNull RMLocalProject project, + @NotNull String projectId, + @NotNull String configuration, + @Nullable List dataSourceIds + ) throws DBException { + if (dataSourceConfigUpdateHandlers.isEmpty()) { + return configuration; + } + + Set projectPermissions = getProjectPermissions(projectId, project.getProjectType()); + String currentConfiguration = serializeProjectDataSourcesConfiguration( + project, + dataSourceIds == null ? null : dataSourceIds.toArray(String[]::new) + ); + String processedConfiguration = configuration; + for (RMDataSourceConfigUpdateHandler handler : dataSourceConfigUpdateHandlers) { + processedConfiguration = handler.processDataSourceConfigurationUpdate( + currentConfiguration, + processedConfiguration, + projectPermissions + ); + } + return processedConfiguration; + } + @Override public void deleteProjectDataSources(@NotNull String projectId, @NotNull String[] dataSourceIds) throws DBException { super.deleteProjectDataSources(projectId, dataSourceIds); diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandler.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandler.java new file mode 100644 index 00000000000..03b07d54b25 --- /dev/null +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandler.java @@ -0,0 +1,32 @@ + /* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2026 DBeaver Corp and others + * + * 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 io.cloudbeaver.model.rm.local; + +import org.jkiss.code.NotNull; +import org.jkiss.dbeaver.DBException; +import org.jkiss.dbeaver.model.rm.RMProjectPermission; + +import java.util.Set; + +public interface RMDataSourceConfigUpdateHandler { + @NotNull + String processDataSourceConfigurationUpdate( + @NotNull String currentConfiguration, + @NotNull String updatedConfiguration, + @NotNull Set projectPermissions + ) throws DBException; +} diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlerDescriptor.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlerDescriptor.java new file mode 100644 index 00000000000..1da255f1b05 --- /dev/null +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlerDescriptor.java @@ -0,0 +1,37 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2026 DBeaver Corp and others + * + * 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 io.cloudbeaver.model.rm.local; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.jkiss.dbeaver.DBException; +import org.jkiss.dbeaver.model.impl.AbstractDescriptor; + +public class RMDataSourceConfigUpdateHandlerDescriptor extends AbstractDescriptor { + public static final String EXTENSION_ID = "io.cloudbeaver.rm.datasource.update.handler"; //$NON-NLS-1$ + + private final RMDataSourceConfigUpdateHandler instance; + + public RMDataSourceConfigUpdateHandlerDescriptor(IConfigurationElement config) throws DBException { + super(config); + ObjectType implClass = new ObjectType(config.getAttribute("class")); + this.instance = implClass.createInstance(RMDataSourceConfigUpdateHandler.class); + } + + public RMDataSourceConfigUpdateHandler getInstance() { + return instance; + } +} diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlersRegistry.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlersRegistry.java new file mode 100644 index 00000000000..c662a2cdc93 --- /dev/null +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlersRegistry.java @@ -0,0 +1,62 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2026 DBeaver Corp and others + * + * 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 io.cloudbeaver.model.rm.local; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.Platform; +import org.jkiss.dbeaver.DBException; +import org.jkiss.dbeaver.Log; + +import java.util.ArrayList; +import java.util.List; + +public class RMDataSourceConfigUpdateHandlersRegistry { + private static final Log log = Log.getLog(RMDataSourceConfigUpdateHandlersRegistry.class); + + private static final String TAG_HANDLER = "rmDataSourceConfigUpdateHandler"; //$NON-NLS-1$ + + private static RMDataSourceConfigUpdateHandlersRegistry instance; + + private final List handlers = new ArrayList<>(); + + public static synchronized RMDataSourceConfigUpdateHandlersRegistry getInstance() { + if (instance == null) { + instance = new RMDataSourceConfigUpdateHandlersRegistry(); + instance.loadExtensions(Platform.getExtensionRegistry()); + } + return instance; + } + + private synchronized void loadExtensions(IExtensionRegistry registry) { + IConfigurationElement[] extConfigs = registry.getConfigurationElementsFor(RMDataSourceConfigUpdateHandlerDescriptor.EXTENSION_ID); + for (IConfigurationElement ext : extConfigs) { + if (!TAG_HANDLER.equals(ext.getName())) { + continue; + } + try { + handlers.add(new RMDataSourceConfigUpdateHandlerDescriptor(ext).getInstance()); + } catch (DBException e) { + log.error("Error loading data source config update handler", e); + } + } + } + + public List getHandlers() { + return handlers; + } +} From bebc4f173f97ec8d30d2578a218485e57d831ec5 Mon Sep 17 00:00:00 2001 From: Ruslan Date: Wed, 15 Apr 2026 19:15:52 +0200 Subject: [PATCH 2/4] dbeaver/pro#8234 only admin can overwrite existing udbt handler --- .../bundles/io.cloudbeaver.model/plugin.xml | 2 + ...eaver.rmDataSourceConfigUpdateHandler.exsd | 11 ++++ .../rm/local/BaseLocalResourceController.java | 51 +++++++++------ .../rm/local/LocalResourceController.java | 30 +++++++++ .../RMDataSourceConfigUpdateHandler.java | 32 ++++++++++ ...taSourceConfigUpdateHandlerDescriptor.java | 37 +++++++++++ ...ataSourceConfigUpdateHandlersRegistry.java | 62 +++++++++++++++++++ 7 files changed, 207 insertions(+), 18 deletions(-) create mode 100644 server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.rmDataSourceConfigUpdateHandler.exsd create mode 100644 server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandler.java create mode 100644 server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlerDescriptor.java create mode 100644 server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlersRegistry.java diff --git a/server/bundles/io.cloudbeaver.model/plugin.xml b/server/bundles/io.cloudbeaver.model/plugin.xml index de60a463385..01d919d5489 100644 --- a/server/bundles/io.cloudbeaver.model/plugin.xml +++ b/server/bundles/io.cloudbeaver.model/plugin.xml @@ -10,6 +10,8 @@ + diff --git a/server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.rmDataSourceConfigUpdateHandler.exsd b/server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.rmDataSourceConfigUpdateHandler.exsd new file mode 100644 index 00000000000..cfa43cbee72 --- /dev/null +++ b/server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.rmDataSourceConfigUpdateHandler.exsd @@ -0,0 +1,11 @@ + + + + + + + + RM data source config update handler + + + diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/BaseLocalResourceController.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/BaseLocalResourceController.java index 3ec793dceba..c1b720568cb 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/BaseLocalResourceController.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/BaseLocalResourceController.java @@ -116,22 +116,7 @@ public String getProjectsDataSources(@NotNull String projectId, @Nullable String return doFileReadOperation( projectId, projectMetadata.getMetadataFolder(false), - () -> { - DBPDataSourceRegistry registry = projectMetadata.getDataSourceRegistry(); - registry.refreshConfig(); - registry.checkForErrors(); - DataSourceConfigurationManagerBuffer buffer = new DataSourceConfigurationManagerBuffer(); - Predicate filter = null; - if (!ArrayUtils.isEmpty(dataSourceIds)) { - filter = ds -> ArrayUtils.contains(dataSourceIds, ds.getId()); - } - ((DataSourcePersistentRegistry) registry).saveConfigurationToManager(new VoidProgressMonitor(), - buffer, - filter); - registry.checkForErrors(); - - return new String(buffer.getData(), StandardCharsets.UTF_8); - } + () -> serializeProjectDataSourcesConfiguration(projectMetadata, dataSourceIds) ); } @@ -160,12 +145,13 @@ protected DataSourceParseResults updateProjectDataSourcesConfig( @Nullable List dataSourceIds ) throws DBException { try (var ignoredLock = lockController.lock(LockTarget.of(projectId), LockOptions.of("updateProjectDataSources"))) { - DBPProject project = getWebProject(projectId, false); + RMLocalProject project = getWebProject(projectId, false); + String processedConfiguration = preprocessDataSourceConfigurationUpdate(project, projectId, configuration, dataSourceIds); return doFileWriteOperation( projectId, project.getMetadataFolder(false), () -> { DBPDataSourceRegistry registry = project.getDataSourceRegistry(); - DBPDataSourceConfigurationStorage storage = new DataSourceMemoryStorage(configuration.getBytes( + DBPDataSourceConfigurationStorage storage = new DataSourceMemoryStorage(processedConfiguration.getBytes( StandardCharsets.UTF_8)); DataSourceConfigurationManager manager = new DataSourceConfigurationManagerBuffer(); final DataSourceParseResults parseResults = ((DataSourcePersistentRegistry) registry).loadDataSources( @@ -185,6 +171,35 @@ protected DataSourceParseResults updateProjectDataSourcesConfig( } } + @NotNull + protected String preprocessDataSourceConfigurationUpdate( + @NotNull RMLocalProject project, + @NotNull String projectId, + @NotNull String configuration, + @Nullable List dataSourceIds + ) throws DBException { + return configuration; + } + + @NotNull + protected String serializeProjectDataSourcesConfiguration( + @NotNull DBPProject project, + @Nullable String[] dataSourceIds + ) throws DBException { + DBPDataSourceRegistry registry = project.getDataSourceRegistry(); + registry.refreshConfig(); + registry.checkForErrors(); + DataSourceConfigurationManagerBuffer buffer = new DataSourceConfigurationManagerBuffer(); + Predicate filter = null; + if (!ArrayUtils.isEmpty(dataSourceIds)) { + filter = ds -> ArrayUtils.contains(dataSourceIds, ds.getId()); + } + ((DataSourcePersistentRegistry) registry).saveConfigurationToManager(new VoidProgressMonitor(), buffer, filter); + registry.checkForErrors(); + + return new String(buffer.getData(), StandardCharsets.UTF_8); + } + @Override public void deleteProjectDataSources( @NotNull String projectId, diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/LocalResourceController.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/LocalResourceController.java index 5a0033c300d..345ed6a5f1d 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/LocalResourceController.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/LocalResourceController.java @@ -82,6 +82,7 @@ public class LocalResourceController extends BaseLocalResourceController { private final String globalProjectName; private Supplier smControllerSupplier; protected final List fileHandlers; + protected final List dataSourceConfigUpdateHandlers; private final Map projectRegistries = new LinkedHashMap<>(); private final ProjectsMetadataInfo sharedProjectsMetadataInfo; @@ -104,6 +105,7 @@ public LocalResourceController( this.globalProjectName = DBWorkbench.getPlatform().getApplication().getDefaultProjectName(); this.fileHandlers = RMFileOperationHandlersRegistry.getInstance().getFileHandlers(); + this.dataSourceConfigUpdateHandlers = RMDataSourceConfigUpdateHandlersRegistry.getInstance().getHandlers(); this.sharedProjectsMetadataInfo = new ProjectsMetadataInfo(sharedProjectsPath, lockController); } @@ -411,6 +413,34 @@ public boolean updateProjectDataSources( return parseResults != null; } + @Override + @NotNull + protected String preprocessDataSourceConfigurationUpdate( + @NotNull RMLocalProject project, + @NotNull String projectId, + @NotNull String configuration, + @Nullable List dataSourceIds + ) throws DBException { + if (dataSourceConfigUpdateHandlers.isEmpty()) { + return configuration; + } + + Set projectPermissions = getProjectPermissions(projectId, project.getProjectType()); + String currentConfiguration = serializeProjectDataSourcesConfiguration( + project, + dataSourceIds == null ? null : dataSourceIds.toArray(String[]::new) + ); + String processedConfiguration = configuration; + for (RMDataSourceConfigUpdateHandler handler : dataSourceConfigUpdateHandlers) { + processedConfiguration = handler.processDataSourceConfigurationUpdate( + currentConfiguration, + processedConfiguration, + projectPermissions + ); + } + return processedConfiguration; + } + @Override public void deleteProjectDataSources(@NotNull String projectId, @NotNull String[] dataSourceIds) throws DBException { super.deleteProjectDataSources(projectId, dataSourceIds); diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandler.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandler.java new file mode 100644 index 00000000000..03b07d54b25 --- /dev/null +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandler.java @@ -0,0 +1,32 @@ + /* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2026 DBeaver Corp and others + * + * 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 io.cloudbeaver.model.rm.local; + +import org.jkiss.code.NotNull; +import org.jkiss.dbeaver.DBException; +import org.jkiss.dbeaver.model.rm.RMProjectPermission; + +import java.util.Set; + +public interface RMDataSourceConfigUpdateHandler { + @NotNull + String processDataSourceConfigurationUpdate( + @NotNull String currentConfiguration, + @NotNull String updatedConfiguration, + @NotNull Set projectPermissions + ) throws DBException; +} diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlerDescriptor.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlerDescriptor.java new file mode 100644 index 00000000000..1da255f1b05 --- /dev/null +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlerDescriptor.java @@ -0,0 +1,37 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2026 DBeaver Corp and others + * + * 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 io.cloudbeaver.model.rm.local; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.jkiss.dbeaver.DBException; +import org.jkiss.dbeaver.model.impl.AbstractDescriptor; + +public class RMDataSourceConfigUpdateHandlerDescriptor extends AbstractDescriptor { + public static final String EXTENSION_ID = "io.cloudbeaver.rm.datasource.update.handler"; //$NON-NLS-1$ + + private final RMDataSourceConfigUpdateHandler instance; + + public RMDataSourceConfigUpdateHandlerDescriptor(IConfigurationElement config) throws DBException { + super(config); + ObjectType implClass = new ObjectType(config.getAttribute("class")); + this.instance = implClass.createInstance(RMDataSourceConfigUpdateHandler.class); + } + + public RMDataSourceConfigUpdateHandler getInstance() { + return instance; + } +} diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlersRegistry.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlersRegistry.java new file mode 100644 index 00000000000..c662a2cdc93 --- /dev/null +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlersRegistry.java @@ -0,0 +1,62 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2026 DBeaver Corp and others + * + * 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 io.cloudbeaver.model.rm.local; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.Platform; +import org.jkiss.dbeaver.DBException; +import org.jkiss.dbeaver.Log; + +import java.util.ArrayList; +import java.util.List; + +public class RMDataSourceConfigUpdateHandlersRegistry { + private static final Log log = Log.getLog(RMDataSourceConfigUpdateHandlersRegistry.class); + + private static final String TAG_HANDLER = "rmDataSourceConfigUpdateHandler"; //$NON-NLS-1$ + + private static RMDataSourceConfigUpdateHandlersRegistry instance; + + private final List handlers = new ArrayList<>(); + + public static synchronized RMDataSourceConfigUpdateHandlersRegistry getInstance() { + if (instance == null) { + instance = new RMDataSourceConfigUpdateHandlersRegistry(); + instance.loadExtensions(Platform.getExtensionRegistry()); + } + return instance; + } + + private synchronized void loadExtensions(IExtensionRegistry registry) { + IConfigurationElement[] extConfigs = registry.getConfigurationElementsFor(RMDataSourceConfigUpdateHandlerDescriptor.EXTENSION_ID); + for (IConfigurationElement ext : extConfigs) { + if (!TAG_HANDLER.equals(ext.getName())) { + continue; + } + try { + handlers.add(new RMDataSourceConfigUpdateHandlerDescriptor(ext).getInstance()); + } catch (DBException e) { + log.error("Error loading data source config update handler", e); + } + } + } + + public List getHandlers() { + return handlers; + } +} From 3e81e5ad564203de67de848ea6e70f4b60c1640e Mon Sep 17 00:00:00 2001 From: Ruslan Date: Mon, 20 Apr 2026 17:09:45 +0200 Subject: [PATCH 3/4] dbeaver/pro#8234 Refactor data source configuration handling and update permission checks --- .../bundles/io.cloudbeaver.model/plugin.xml | 2 - ...eaver.rmDataSourceConfigUpdateHandler.exsd | 11 -- .../rm/local/BaseLocalResourceController.java | 34 +++-- .../rm/local/LocalResourceController.java | 116 ++++++++++++++---- .../RMDataSourceConfigUpdateHandler.java | 32 ----- ...taSourceConfigUpdateHandlerDescriptor.java | 37 ------ ...ataSourceConfigUpdateHandlersRegistry.java | 62 ---------- 7 files changed, 122 insertions(+), 172 deletions(-) delete mode 100644 server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.rmDataSourceConfigUpdateHandler.exsd delete mode 100644 server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandler.java delete mode 100644 server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlerDescriptor.java delete mode 100644 server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlersRegistry.java diff --git a/server/bundles/io.cloudbeaver.model/plugin.xml b/server/bundles/io.cloudbeaver.model/plugin.xml index 01d919d5489..de60a463385 100644 --- a/server/bundles/io.cloudbeaver.model/plugin.xml +++ b/server/bundles/io.cloudbeaver.model/plugin.xml @@ -10,8 +10,6 @@ - diff --git a/server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.rmDataSourceConfigUpdateHandler.exsd b/server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.rmDataSourceConfigUpdateHandler.exsd deleted file mode 100644 index cfa43cbee72..00000000000 --- a/server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.rmDataSourceConfigUpdateHandler.exsd +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - RM data source config update handler - - - diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/BaseLocalResourceController.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/BaseLocalResourceController.java index c1b720568cb..9fe1d41d075 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/BaseLocalResourceController.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/BaseLocalResourceController.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry; import org.jkiss.dbeaver.model.app.DBPProject; import org.jkiss.dbeaver.model.app.DBPWorkspace; +import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration; import org.jkiss.dbeaver.model.fs.lock.LockManager; import org.jkiss.dbeaver.model.fs.lock.LockOptions; import org.jkiss.dbeaver.model.fs.lock.LockTarget; @@ -45,6 +46,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; +import java.util.Map; import java.util.function.Predicate; public abstract class BaseLocalResourceController implements RMController { @@ -146,12 +148,13 @@ protected DataSourceParseResults updateProjectDataSourcesConfig( ) throws DBException { try (var ignoredLock = lockController.lock(LockTarget.of(projectId), LockOptions.of("updateProjectDataSources"))) { RMLocalProject project = getWebProject(projectId, false); - String processedConfiguration = preprocessDataSourceConfigurationUpdate(project, projectId, configuration, dataSourceIds); + Map storedDataSourceConfigurations = + captureCurrentDataSourceConfigurations(project, dataSourceIds); return doFileWriteOperation( projectId, project.getMetadataFolder(false), () -> { DBPDataSourceRegistry registry = project.getDataSourceRegistry(); - DBPDataSourceConfigurationStorage storage = new DataSourceMemoryStorage(processedConfiguration.getBytes( + DBPDataSourceConfigurationStorage storage = new DataSourceMemoryStorage(configuration.getBytes( StandardCharsets.UTF_8)); DataSourceConfigurationManager manager = new DataSourceConfigurationManagerBuffer(); final DataSourceParseResults parseResults = ((DataSourcePersistentRegistry) registry).loadDataSources( @@ -162,6 +165,17 @@ protected DataSourceParseResults updateProjectDataSourcesConfig( dataSourceIds == null ); registry.checkForErrors(); + try { + processLoadedDataSourceConfigurationUpdate( + project, + projectId, + dataSourceIds, + storedDataSourceConfigurations + ); + } catch (DBException e) { + registry.refreshConfig(); + registry.checkForErrors(); + } log.debug("Save data sources configuration in project '" + projectId + "'"); ((DataSourcePersistentRegistry) registry).saveDataSources(); registry.checkForErrors(); @@ -172,13 +186,19 @@ protected DataSourceParseResults updateProjectDataSourcesConfig( } @NotNull - protected String preprocessDataSourceConfigurationUpdate( + protected Map captureCurrentDataSourceConfigurations( @NotNull RMLocalProject project, - @NotNull String projectId, - @NotNull String configuration, @Nullable List dataSourceIds + ) { + return Map.of(); + } + + protected void processLoadedDataSourceConfigurationUpdate( + @NotNull RMLocalProject project, + @NotNull String projectId, + @Nullable List dataSourceIds, + @NotNull Map storedDataSourceConfigurations ) throws DBException { - return configuration; } @NotNull diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/LocalResourceController.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/LocalResourceController.java index 345ed6a5f1d..e581f7a6115 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/LocalResourceController.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/LocalResourceController.java @@ -33,12 +33,14 @@ import org.jkiss.dbeaver.model.app.DBPWorkspace; import org.jkiss.dbeaver.model.auth.SMCredentials; import org.jkiss.dbeaver.model.auth.SMCredentialsProvider; +import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration; import org.jkiss.dbeaver.model.fs.lock.LockManager; import org.jkiss.dbeaver.model.fs.lock.LockOptions; import org.jkiss.dbeaver.model.fs.lock.LockTarget; import org.jkiss.dbeaver.model.impl.app.BaseProjectImpl; import org.jkiss.dbeaver.model.impl.auth.SessionContextImpl; import org.jkiss.dbeaver.model.navigator.DBNLocalFolder; +import org.jkiss.dbeaver.model.net.DBWHandlerConfiguration; import org.jkiss.dbeaver.model.rm.*; import org.jkiss.dbeaver.model.security.SMAdminController; import org.jkiss.dbeaver.model.security.SMObjectType; @@ -52,6 +54,7 @@ import org.jkiss.dbeaver.registry.DataSourceParseResults; import org.jkiss.dbeaver.registry.ResourceTypeDescriptor; import org.jkiss.dbeaver.registry.ResourceTypeRegistry; +import org.jkiss.dbeaver.registry.network.NetworkHandlerDescriptor; import org.jkiss.dbeaver.runtime.DBWorkbench; import org.jkiss.utils.CommonUtils; import org.jkiss.utils.IOUtils; @@ -82,7 +85,6 @@ public class LocalResourceController extends BaseLocalResourceController { private final String globalProjectName; private Supplier smControllerSupplier; protected final List fileHandlers; - protected final List dataSourceConfigUpdateHandlers; private final Map projectRegistries = new LinkedHashMap<>(); private final ProjectsMetadataInfo sharedProjectsMetadataInfo; @@ -105,7 +107,6 @@ public LocalResourceController( this.globalProjectName = DBWorkbench.getPlatform().getApplication().getDefaultProjectName(); this.fileHandlers = RMFileOperationHandlersRegistry.getInstance().getFileHandlers(); - this.dataSourceConfigUpdateHandlers = RMDataSourceConfigUpdateHandlersRegistry.getInstance().getHandlers(); this.sharedProjectsMetadataInfo = new ProjectsMetadataInfo(sharedProjectsPath, lockController); } @@ -415,30 +416,103 @@ public boolean updateProjectDataSources( @Override @NotNull - protected String preprocessDataSourceConfigurationUpdate( + protected Map captureCurrentDataSourceConfigurations( @NotNull RMLocalProject project, - @NotNull String projectId, - @NotNull String configuration, @Nullable List dataSourceIds + ) { + return project.getDataSourceRegistry().getDataSources().stream() + .filter(ds -> dataSourceIds == null || dataSourceIds.contains(ds.getId())) + .collect(Collectors.toMap( + DBPDataSourceContainer::getId, + ds -> new DBPConnectionConfiguration(ds.getConnectionConfiguration()) + )); + } + + @Override + protected void processLoadedDataSourceConfigurationUpdate( + @NotNull RMLocalProject project, + @NotNull String projectId, + @Nullable List dataSourceIds, + @NotNull Map storedDataSourceConfigurations ) throws DBException { - if (dataSourceConfigUpdateHandlers.isEmpty()) { - return configuration; - } - - Set projectPermissions = getProjectPermissions(projectId, project.getProjectType()); - String currentConfiguration = serializeProjectDataSourcesConfiguration( - project, - dataSourceIds == null ? null : dataSourceIds.toArray(String[]::new) - ); - String processedConfiguration = configuration; - for (RMDataSourceConfigUpdateHandler handler : dataSourceConfigUpdateHandlers) { - processedConfiguration = handler.processDataSourceConfigurationUpdate( - currentConfiguration, - processedConfiguration, - projectPermissions + Set userProjectPermissions = getProjectPermissions(projectId, project.getProjectType()); + Set grantedPermissions = userProjectPermissions.stream() + .flatMap(permission -> permission.getAllPermissions().stream()) + .collect(Collectors.toSet()); + + for (DBPDataSourceContainer dataSource : project.getDataSourceRegistry().getDataSources()) { + if (dataSourceIds != null && !dataSourceIds.contains(dataSource.getId())) { + continue; + } + + DBPConnectionConfiguration storedConfiguration = storedDataSourceConfigurations.get(dataSource.getId()); + reconcileNetworkHandlers( + storedConfiguration, + dataSource.getConnectionConfiguration(), + grantedPermissions ); } - return processedConfiguration; + } + + private void reconcileNetworkHandlers( + @Nullable DBPConnectionConfiguration storedConfiguration, + @NotNull DBPConnectionConfiguration updatedConfiguration, + @NotNull Set grantedPermissions + ) throws DBException { + + // Getting all handlers ids from both stored and updated configurations to check permissions for all of them + // and to add missing handlers if user has no permissions to add new ones + Set handlerIds = new LinkedHashSet<>(); + if (storedConfiguration != null) { + storedConfiguration.getHandlers().stream() + .map(DBWHandlerConfiguration::getId) + .forEach(handlerIds::add); + } + updatedConfiguration.getHandlers().stream() + .map(DBWHandlerConfiguration::getId) + .forEach(handlerIds::add); + + for (String handlerId : handlerIds) { + DBWHandlerConfiguration storedHandler = storedConfiguration == null ? null : storedConfiguration.getHandler(handlerId); + DBWHandlerConfiguration updatedHandler = updatedConfiguration.getHandler(handlerId); + DBWHandlerConfiguration descriptorSource = updatedHandler != null ? updatedHandler : storedHandler; + if (descriptorSource == null + || !(descriptorSource.getHandlerDescriptor() instanceof NetworkHandlerDescriptor descriptor)) { + continue; + } + + if (descriptor.getRequiredPermissions().isEmpty() + || grantedPermissions.containsAll(descriptor.getRequiredPermissions())) { + continue; + } + + if (storedHandler == null) { + throw new DBException("No permissions to configure network handler '" + handlerId + "'"); + } + + // if user doesn't have permissions to add new handler, we should keep old one + if (updatedHandler == null) { + updatedConfiguration.updateHandler(new DBWHandlerConfiguration(storedHandler)); + continue; + } + + if (!areSameHandlerConfiguration(storedHandler, updatedHandler)) { + throw new DBException("No permissions to modify network handler '" + handlerId + "'"); + } + } + } + + private boolean areSameHandlerConfiguration( + @NotNull DBWHandlerConfiguration storedHandler, + @NotNull DBWHandlerConfiguration updatedHandler + ) { + DBWHandlerConfiguration storedHandlerCopy = new DBWHandlerConfiguration(storedHandler); + storedHandlerCopy.setDataSource(null); + + DBWHandlerConfiguration updatedHandlerCopy = new DBWHandlerConfiguration(updatedHandler); + updatedHandlerCopy.setDataSource(null); + + return storedHandlerCopy.equals(updatedHandlerCopy); } @Override diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandler.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandler.java deleted file mode 100644 index 03b07d54b25..00000000000 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandler.java +++ /dev/null @@ -1,32 +0,0 @@ - /* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2026 DBeaver Corp and others - * - * 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 io.cloudbeaver.model.rm.local; - -import org.jkiss.code.NotNull; -import org.jkiss.dbeaver.DBException; -import org.jkiss.dbeaver.model.rm.RMProjectPermission; - -import java.util.Set; - -public interface RMDataSourceConfigUpdateHandler { - @NotNull - String processDataSourceConfigurationUpdate( - @NotNull String currentConfiguration, - @NotNull String updatedConfiguration, - @NotNull Set projectPermissions - ) throws DBException; -} diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlerDescriptor.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlerDescriptor.java deleted file mode 100644 index 1da255f1b05..00000000000 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlerDescriptor.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2026 DBeaver Corp and others - * - * 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 io.cloudbeaver.model.rm.local; - -import org.eclipse.core.runtime.IConfigurationElement; -import org.jkiss.dbeaver.DBException; -import org.jkiss.dbeaver.model.impl.AbstractDescriptor; - -public class RMDataSourceConfigUpdateHandlerDescriptor extends AbstractDescriptor { - public static final String EXTENSION_ID = "io.cloudbeaver.rm.datasource.update.handler"; //$NON-NLS-1$ - - private final RMDataSourceConfigUpdateHandler instance; - - public RMDataSourceConfigUpdateHandlerDescriptor(IConfigurationElement config) throws DBException { - super(config); - ObjectType implClass = new ObjectType(config.getAttribute("class")); - this.instance = implClass.createInstance(RMDataSourceConfigUpdateHandler.class); - } - - public RMDataSourceConfigUpdateHandler getInstance() { - return instance; - } -} diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlersRegistry.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlersRegistry.java deleted file mode 100644 index c662a2cdc93..00000000000 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlersRegistry.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2026 DBeaver Corp and others - * - * 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 io.cloudbeaver.model.rm.local; - -import org.eclipse.core.runtime.IConfigurationElement; -import org.eclipse.core.runtime.IExtensionRegistry; -import org.eclipse.core.runtime.Platform; -import org.jkiss.dbeaver.DBException; -import org.jkiss.dbeaver.Log; - -import java.util.ArrayList; -import java.util.List; - -public class RMDataSourceConfigUpdateHandlersRegistry { - private static final Log log = Log.getLog(RMDataSourceConfigUpdateHandlersRegistry.class); - - private static final String TAG_HANDLER = "rmDataSourceConfigUpdateHandler"; //$NON-NLS-1$ - - private static RMDataSourceConfigUpdateHandlersRegistry instance; - - private final List handlers = new ArrayList<>(); - - public static synchronized RMDataSourceConfigUpdateHandlersRegistry getInstance() { - if (instance == null) { - instance = new RMDataSourceConfigUpdateHandlersRegistry(); - instance.loadExtensions(Platform.getExtensionRegistry()); - } - return instance; - } - - private synchronized void loadExtensions(IExtensionRegistry registry) { - IConfigurationElement[] extConfigs = registry.getConfigurationElementsFor(RMDataSourceConfigUpdateHandlerDescriptor.EXTENSION_ID); - for (IConfigurationElement ext : extConfigs) { - if (!TAG_HANDLER.equals(ext.getName())) { - continue; - } - try { - handlers.add(new RMDataSourceConfigUpdateHandlerDescriptor(ext).getInstance()); - } catch (DBException e) { - log.error("Error loading data source config update handler", e); - } - } - } - - public List getHandlers() { - return handlers; - } -} From d1500b1dd6273a3e28d9dbaed00e436ea397dee6 Mon Sep 17 00:00:00 2001 From: Ruslan Date: Mon, 20 Apr 2026 17:33:14 +0200 Subject: [PATCH 4/4] dbeaver/pro#8234 fixes --- .../bundles/io.cloudbeaver.model/plugin.xml | 2 - ...eaver.rmDataSourceConfigUpdateHandler.exsd | 11 ---- .../rm/local/BaseLocalResourceController.java | 37 +++++------ .../RMDataSourceConfigUpdateHandler.java | 32 ---------- ...taSourceConfigUpdateHandlerDescriptor.java | 37 ----------- ...ataSourceConfigUpdateHandlersRegistry.java | 62 ------------------- 6 files changed, 16 insertions(+), 165 deletions(-) delete mode 100644 server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.rmDataSourceConfigUpdateHandler.exsd delete mode 100644 server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandler.java delete mode 100644 server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlerDescriptor.java delete mode 100644 server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlersRegistry.java diff --git a/server/bundles/io.cloudbeaver.model/plugin.xml b/server/bundles/io.cloudbeaver.model/plugin.xml index 01d919d5489..de60a463385 100644 --- a/server/bundles/io.cloudbeaver.model/plugin.xml +++ b/server/bundles/io.cloudbeaver.model/plugin.xml @@ -10,8 +10,6 @@ - diff --git a/server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.rmDataSourceConfigUpdateHandler.exsd b/server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.rmDataSourceConfigUpdateHandler.exsd deleted file mode 100644 index cfa43cbee72..00000000000 --- a/server/bundles/io.cloudbeaver.model/schema/io.cloudbeaver.rmDataSourceConfigUpdateHandler.exsd +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - RM data source config update handler - - - diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/BaseLocalResourceController.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/BaseLocalResourceController.java index 9fe1d41d075..3a02af3beec 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/BaseLocalResourceController.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/BaseLocalResourceController.java @@ -118,7 +118,22 @@ public String getProjectsDataSources(@NotNull String projectId, @Nullable String return doFileReadOperation( projectId, projectMetadata.getMetadataFolder(false), - () -> serializeProjectDataSourcesConfiguration(projectMetadata, dataSourceIds) + () -> { + DBPDataSourceRegistry registry = projectMetadata.getDataSourceRegistry(); + registry.refreshConfig(); + registry.checkForErrors(); + DataSourceConfigurationManagerBuffer buffer = new DataSourceConfigurationManagerBuffer(); + Predicate filter = null; + if (!ArrayUtils.isEmpty(dataSourceIds)) { + filter = ds -> ArrayUtils.contains(dataSourceIds, ds.getId()); + } + ((DataSourcePersistentRegistry) registry).saveConfigurationToManager(new VoidProgressMonitor(), + buffer, + filter); + registry.checkForErrors(); + + return new String(buffer.getData(), StandardCharsets.UTF_8); + } ); } @@ -173,7 +188,6 @@ protected DataSourceParseResults updateProjectDataSourcesConfig( storedDataSourceConfigurations ); } catch (DBException e) { - registry.refreshConfig(); registry.checkForErrors(); } log.debug("Save data sources configuration in project '" + projectId + "'"); @@ -201,25 +215,6 @@ protected void processLoadedDataSourceConfigurationUpdate( ) throws DBException { } - @NotNull - protected String serializeProjectDataSourcesConfiguration( - @NotNull DBPProject project, - @Nullable String[] dataSourceIds - ) throws DBException { - DBPDataSourceRegistry registry = project.getDataSourceRegistry(); - registry.refreshConfig(); - registry.checkForErrors(); - DataSourceConfigurationManagerBuffer buffer = new DataSourceConfigurationManagerBuffer(); - Predicate filter = null; - if (!ArrayUtils.isEmpty(dataSourceIds)) { - filter = ds -> ArrayUtils.contains(dataSourceIds, ds.getId()); - } - ((DataSourcePersistentRegistry) registry).saveConfigurationToManager(new VoidProgressMonitor(), buffer, filter); - registry.checkForErrors(); - - return new String(buffer.getData(), StandardCharsets.UTF_8); - } - @Override public void deleteProjectDataSources( @NotNull String projectId, diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandler.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandler.java deleted file mode 100644 index 03b07d54b25..00000000000 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandler.java +++ /dev/null @@ -1,32 +0,0 @@ - /* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2026 DBeaver Corp and others - * - * 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 io.cloudbeaver.model.rm.local; - -import org.jkiss.code.NotNull; -import org.jkiss.dbeaver.DBException; -import org.jkiss.dbeaver.model.rm.RMProjectPermission; - -import java.util.Set; - -public interface RMDataSourceConfigUpdateHandler { - @NotNull - String processDataSourceConfigurationUpdate( - @NotNull String currentConfiguration, - @NotNull String updatedConfiguration, - @NotNull Set projectPermissions - ) throws DBException; -} diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlerDescriptor.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlerDescriptor.java deleted file mode 100644 index 1da255f1b05..00000000000 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlerDescriptor.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2026 DBeaver Corp and others - * - * 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 io.cloudbeaver.model.rm.local; - -import org.eclipse.core.runtime.IConfigurationElement; -import org.jkiss.dbeaver.DBException; -import org.jkiss.dbeaver.model.impl.AbstractDescriptor; - -public class RMDataSourceConfigUpdateHandlerDescriptor extends AbstractDescriptor { - public static final String EXTENSION_ID = "io.cloudbeaver.rm.datasource.update.handler"; //$NON-NLS-1$ - - private final RMDataSourceConfigUpdateHandler instance; - - public RMDataSourceConfigUpdateHandlerDescriptor(IConfigurationElement config) throws DBException { - super(config); - ObjectType implClass = new ObjectType(config.getAttribute("class")); - this.instance = implClass.createInstance(RMDataSourceConfigUpdateHandler.class); - } - - public RMDataSourceConfigUpdateHandler getInstance() { - return instance; - } -} diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlersRegistry.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlersRegistry.java deleted file mode 100644 index c662a2cdc93..00000000000 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/local/RMDataSourceConfigUpdateHandlersRegistry.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2026 DBeaver Corp and others - * - * 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 io.cloudbeaver.model.rm.local; - -import org.eclipse.core.runtime.IConfigurationElement; -import org.eclipse.core.runtime.IExtensionRegistry; -import org.eclipse.core.runtime.Platform; -import org.jkiss.dbeaver.DBException; -import org.jkiss.dbeaver.Log; - -import java.util.ArrayList; -import java.util.List; - -public class RMDataSourceConfigUpdateHandlersRegistry { - private static final Log log = Log.getLog(RMDataSourceConfigUpdateHandlersRegistry.class); - - private static final String TAG_HANDLER = "rmDataSourceConfigUpdateHandler"; //$NON-NLS-1$ - - private static RMDataSourceConfigUpdateHandlersRegistry instance; - - private final List handlers = new ArrayList<>(); - - public static synchronized RMDataSourceConfigUpdateHandlersRegistry getInstance() { - if (instance == null) { - instance = new RMDataSourceConfigUpdateHandlersRegistry(); - instance.loadExtensions(Platform.getExtensionRegistry()); - } - return instance; - } - - private synchronized void loadExtensions(IExtensionRegistry registry) { - IConfigurationElement[] extConfigs = registry.getConfigurationElementsFor(RMDataSourceConfigUpdateHandlerDescriptor.EXTENSION_ID); - for (IConfigurationElement ext : extConfigs) { - if (!TAG_HANDLER.equals(ext.getName())) { - continue; - } - try { - handlers.add(new RMDataSourceConfigUpdateHandlerDescriptor(ext).getInstance()); - } catch (DBException e) { - log.error("Error loading data source config update handler", e); - } - } - } - - public List getHandlers() { - return handlers; - } -}