mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
dbeaver/pro#8824 Inject lock manager into CloudBeaver RM controllers (#4242)
* dbeaver/pro#8824 Inject lock manager into CloudBeaver RM controllers * dbeaver/pro#8824 Use application lock manager provider in servlet applications * dbeaver/pro#8824 Use default application lock manager * dbeaver/pro#8824 Fix codestyle warnings --------- Co-authored-by: Daria Markaryan <43252954+DariaMarkaryan@users.noreply.github.com> Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com> Co-authored-by: Serge Rider <serge@jkiss.org>
This commit is contained in:
co-authored by
Daria Markaryan
mr-anton-t
Serge Rider
parent
321d45bd48
commit
9c1678c256
+18
-2
@@ -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.
|
||||
@@ -25,10 +25,13 @@ import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.DBFileController;
|
||||
import org.jkiss.dbeaver.model.app.DBPLockManagerProvider;
|
||||
import org.jkiss.dbeaver.model.app.DBPWorkspace;
|
||||
import org.jkiss.dbeaver.model.auth.SMCredentialsProvider;
|
||||
import org.jkiss.dbeaver.model.auth.SMSessionContext;
|
||||
import org.jkiss.dbeaver.model.data.json.JSONUtils;
|
||||
import org.jkiss.dbeaver.model.fs.lock.LockManager;
|
||||
import org.jkiss.dbeaver.model.fs.lock.shared.SharedFileLockManager;
|
||||
import org.jkiss.dbeaver.model.impl.app.ApplicationRegistry;
|
||||
import org.jkiss.dbeaver.model.impl.app.BaseApplicationImpl;
|
||||
import org.jkiss.dbeaver.model.impl.app.BaseWorkspaceImpl;
|
||||
@@ -48,7 +51,7 @@ import java.util.Map;
|
||||
/**
|
||||
* Servlet application
|
||||
*/
|
||||
public abstract class BaseServletApplication extends BaseApplicationImpl implements ServletApplication {
|
||||
public abstract class BaseServletApplication extends BaseApplicationImpl implements ServletApplication, DBPLockManagerProvider {
|
||||
|
||||
public static final String DEFAULT_CONFIG_FILE_PATH = "/etc/cloudbeaver.conf";
|
||||
public static final String CUSTOM_CONFIG_FOLDER = "custom";
|
||||
@@ -59,6 +62,7 @@ public abstract class BaseServletApplication extends BaseApplicationImpl impleme
|
||||
|
||||
private String instanceId;
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public RMController createResourceController(
|
||||
@NotNull SMCredentialsProvider credentialsProvider,
|
||||
@@ -73,6 +77,18 @@ public abstract class BaseServletApplication extends BaseApplicationImpl impleme
|
||||
throw new IllegalStateException("File controller is not supported by " + getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public LockManager createLockManager(@NotNull Path metadataFolder) throws DBException {
|
||||
return new SharedFileLockManager(getApplicationInstanceId(), metadataFolder);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public LockManager createLockManager() throws DBException {
|
||||
return new SharedFileLockManager(getApplicationInstanceId());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Path getDefaultWorkingFolder() {
|
||||
|
||||
+10
-8
@@ -26,7 +26,9 @@ import org.jkiss.dbeaver.model.DBPDataSourceFolder;
|
||||
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.fs.lock.FileLockController;
|
||||
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.rm.RMController;
|
||||
import org.jkiss.dbeaver.model.rm.RMEvent;
|
||||
import org.jkiss.dbeaver.model.rm.RMEventManager;
|
||||
@@ -53,11 +55,11 @@ public abstract class BaseLocalResourceController implements RMController {
|
||||
@NotNull
|
||||
protected final DBPWorkspace workspace;
|
||||
@NotNull
|
||||
protected final FileLockController lockController;
|
||||
protected final LockManager lockController;
|
||||
|
||||
protected BaseLocalResourceController(
|
||||
@NotNull DBPWorkspace workspace,
|
||||
@NotNull FileLockController lockController
|
||||
@NotNull LockManager lockController
|
||||
) {
|
||||
this.workspace = workspace;
|
||||
this.lockController = lockController;
|
||||
@@ -157,7 +159,7 @@ public abstract class BaseLocalResourceController implements RMController {
|
||||
@NotNull String configuration,
|
||||
@Nullable List<String> dataSourceIds
|
||||
) throws DBException {
|
||||
try (var ignoredLock = lockController.lock(projectId, "updateProjectDataSources")) {
|
||||
try (var ignoredLock = lockController.lock(LockTarget.of(projectId), LockOptions.of("updateProjectDataSources"))) {
|
||||
DBPProject project = getWebProject(projectId, false);
|
||||
return doFileWriteOperation(
|
||||
projectId, project.getMetadataFolder(false),
|
||||
@@ -188,7 +190,7 @@ public abstract class BaseLocalResourceController implements RMController {
|
||||
@NotNull String projectId,
|
||||
@NotNull String[] dataSourceIds
|
||||
) throws DBException {
|
||||
try (var ignoredLock = lockController.lock(projectId, "deleteDataSources")) {
|
||||
try (var ignoredLock = lockController.lock(LockTarget.of(projectId), LockOptions.of("deleteDataSources"))) {
|
||||
DBPProject project = getWebProject(projectId, false);
|
||||
doFileWriteOperation(projectId, project.getMetadataFolder(false), () -> {
|
||||
DBPDataSourceRegistry registry = project.getDataSourceRegistry();
|
||||
@@ -213,7 +215,7 @@ public abstract class BaseLocalResourceController implements RMController {
|
||||
@NotNull String projectId,
|
||||
@NotNull String folderPath
|
||||
) throws DBException {
|
||||
try (var ignoredLock = lockController.lock(projectId, "createDatasourceFolder")) {
|
||||
try (var ignoredLock = lockController.lock(LockTarget.of(projectId), LockOptions.of("createDatasourceFolder"))) {
|
||||
DBPProject project = getWebProject(projectId, false);
|
||||
log.debug("Creating data source folder '" + folderPath + "' in project '" + projectId + "'");
|
||||
doFileWriteOperation(projectId, project.getMetadataFolder(false),
|
||||
@@ -241,7 +243,7 @@ public abstract class BaseLocalResourceController implements RMController {
|
||||
@NotNull String[] folderPaths,
|
||||
boolean dropContents
|
||||
) throws DBException {
|
||||
try (var ignoredLock = lockController.lock(projectId, "createDatasourceFolder")) {
|
||||
try (var ignoredLock = lockController.lock(LockTarget.of(projectId), LockOptions.of("createDatasourceFolder"))) {
|
||||
DBPProject project = getWebProject(projectId, false);
|
||||
doFileWriteOperation(projectId, project.getMetadataFolder(false),
|
||||
() -> {
|
||||
@@ -267,7 +269,7 @@ public abstract class BaseLocalResourceController implements RMController {
|
||||
@NotNull String oldPath,
|
||||
@NotNull String newPath
|
||||
) throws DBException {
|
||||
try (var ignoredLock = lockController.lock(projectId, "createDatasourceFolder")) {
|
||||
try (var ignoredLock = lockController.lock(LockTarget.of(projectId), LockOptions.of("createDatasourceFolder"))) {
|
||||
DBPProject project = getWebProject(projectId, false);
|
||||
log.debug("Moving data source folder from '" + oldPath + "' to '" + newPath + "' in project '" + projectId + "'");
|
||||
doFileWriteOperation(projectId, project.getMetadataFolder(false),
|
||||
|
||||
+44
-23
@@ -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.
|
||||
@@ -33,7 +33,9 @@ import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry;
|
||||
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.fs.lock.FileLockController;
|
||||
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;
|
||||
@@ -90,9 +92,10 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
@NotNull Path rootPath,
|
||||
@NotNull Path userProjectsPath,
|
||||
@NotNull Path sharedProjectsPath,
|
||||
@NotNull Supplier<SMAdminController> smControllerSupplier
|
||||
@NotNull Supplier<SMAdminController> smControllerSupplier,
|
||||
@NotNull LockManager lockController
|
||||
) throws DBException {
|
||||
super(workspace, new FileLockController(ServletAppUtils.getServletApplication().getApplicationInstanceId()));
|
||||
super(workspace, lockController);
|
||||
this.credentialsProvider = credentialsProvider;
|
||||
this.rootPath = rootPath;
|
||||
this.userProjectsPath = userProjectsPath;
|
||||
@@ -101,7 +104,7 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
|
||||
this.globalProjectName = DBWorkbench.getPlatform().getApplication().getDefaultProjectName();
|
||||
this.fileHandlers = RMFileOperationHandlersRegistry.getInstance().getFileHandlers();
|
||||
this.sharedProjectsMetadataInfo = new ProjectsMetadataInfo(sharedProjectsPath);
|
||||
this.sharedProjectsMetadataInfo = new ProjectsMetadataInfo(sharedProjectsPath, lockController);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -303,7 +306,7 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
@Override
|
||||
public RMProject updateProject(@NotNull String projectId, @NotNull RMProjectInfo projectInfo) throws DBException {
|
||||
validateProjectName(projectId, projectInfo.getName());
|
||||
try (var ignoredLock = lockController.lock(projectId, "updateProject")) {
|
||||
try (var ignoredLock = lockController.lock(LockTarget.of(projectId), LockOptions.of("updateProject"))) {
|
||||
RMLocalProject project = getWebProject(projectId, false);
|
||||
Path targetPath = getProjectPath(projectId);
|
||||
if (!Files.exists(targetPath)) {
|
||||
@@ -330,7 +333,7 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
|
||||
@Override
|
||||
public void deleteProject(@NotNull String projectId) throws DBException {
|
||||
try (var ignoredLock = lockController.lock(projectId, "deleteProject")) {
|
||||
try (var ignoredLock = lockController.lock(LockTarget.of(projectId), LockOptions.of("deleteProject"))) {
|
||||
Path targetPath = getProjectPath(projectId);
|
||||
if (!Files.exists(targetPath)) {
|
||||
log.error(MessageFormat.format("Project folder ''{0}'' is not found", projectId));
|
||||
@@ -699,7 +702,7 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
@NotNull String resourcePath,
|
||||
boolean isFolder
|
||||
) throws DBException {
|
||||
try (var ignoredLock = lockController.lock(projectId, "createResource")) {
|
||||
try (var ignoredLock = lockController.lock(LockTarget.of(projectId), LockOptions.of("createResource"))) {
|
||||
validateResourcePath(resourcePath);
|
||||
Path targetPath = getTargetPath(projectId, resourcePath);
|
||||
if (Files.exists(targetPath)) {
|
||||
@@ -731,7 +734,7 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
@NotNull String oldResourcePath,
|
||||
@NotNull String newResourcePath
|
||||
) throws DBException {
|
||||
try (var ignoredLock = lockController.lock(projectId, "moveResource")) {
|
||||
try (var ignoredLock = lockController.lock(LockTarget.of(projectId), LockOptions.of("moveResource"))) {
|
||||
var normalizedOldResourcePath = CommonUtils.normalizeResourcePath(oldResourcePath);
|
||||
var normalizedNewResourcePath = CommonUtils.normalizeResourcePath(newResourcePath);
|
||||
if (log.isDebugEnabled()) {
|
||||
@@ -803,7 +806,7 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
|
||||
@Override
|
||||
public void deleteResource(@NotNull String projectId, @NotNull String resourcePath, boolean recursive) throws DBException {
|
||||
try (var ignoredLock = lockController.lock(projectId, "deleteResource")) {
|
||||
try (var ignoredLock = lockController.lock(LockTarget.of(projectId), LockOptions.of("deleteResource"))) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Removing resource from '" + resourcePath + "' in project '" + projectId + "'" + (recursive ? " recursive" : ""));
|
||||
}
|
||||
@@ -891,7 +894,7 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
@NotNull byte[] data,
|
||||
boolean forceOverwrite
|
||||
) throws DBException {
|
||||
try (var ignoredLock = lockController.lock(projectId, "setResourceContents")) {
|
||||
try (var ignoredLock = lockController.lock(LockTarget.of(projectId), LockOptions.of("setResourceContents"))) {
|
||||
validateResourcePath(resourcePath);
|
||||
Number fileSizeLimit = ServletAppUtils.getServletApplication()
|
||||
.getAppConfiguration()
|
||||
@@ -936,7 +939,7 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
@NotNull String propertyName,
|
||||
@Nullable Object propertyValue
|
||||
) throws DBException {
|
||||
try (var ignoredLock = lockController.lock(projectId, "resourcePropertyUpdate")) {
|
||||
try (var ignoredLock = lockController.lock(LockTarget.of(projectId), LockOptions.of("resourcePropertyUpdate"))) {
|
||||
validateResourcePath(resourcePath);
|
||||
RMLocalProject webProject = getWebProject(projectId, false);
|
||||
doFileWriteOperation(projectId, webProject.getMetadataFilePath(),
|
||||
@@ -957,7 +960,7 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
@NotNull String resourcePath,
|
||||
@NotNull Map<String, Object> properties
|
||||
) throws DBException {
|
||||
try (var ignoredLock = lockController.lock(projectId, "resourcePropertyUpdate")) {
|
||||
try (var ignoredLock = lockController.lock(LockTarget.of(projectId), LockOptions.of("resourcePropertyUpdate"))) {
|
||||
validateResourcePath(resourcePath);
|
||||
RMLocalProject webProject = getWebProject(projectId, false);
|
||||
doFileWriteOperation(projectId, webProject.getMetadataFilePath(),
|
||||
@@ -1204,12 +1207,14 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
return getProjectPath(projectId).toAbsolutePath().relativize(path).toString().replace('\\', IPath.SEPARATOR);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Builder builder(
|
||||
SMCredentialsProvider credentialsProvider,
|
||||
DBPWorkspace workspace,
|
||||
Supplier<SMAdminController> smControllerSupplier
|
||||
@NotNull SMCredentialsProvider credentialsProvider,
|
||||
@NotNull DBPWorkspace workspace,
|
||||
@NotNull LockManager lockController,
|
||||
@NotNull Supplier<SMAdminController> smControllerSupplier
|
||||
) {
|
||||
return new Builder(workspace, credentialsProvider, smControllerSupplier);
|
||||
return new Builder(workspace, credentialsProvider, lockController, smControllerSupplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1225,10 +1230,13 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
protected Path rootPath;
|
||||
protected Path userProjectsPath;
|
||||
protected Path sharedProjectsPath;
|
||||
protected LockManager lockController;
|
||||
|
||||
protected Builder(
|
||||
DBPWorkspace workspace, SMCredentialsProvider credentialsProvider,
|
||||
Supplier<SMAdminController> smControllerSupplier
|
||||
@NotNull DBPWorkspace workspace,
|
||||
@NotNull SMCredentialsProvider credentialsProvider,
|
||||
@NotNull LockManager lockController,
|
||||
@NotNull Supplier<SMAdminController> smControllerSupplier
|
||||
) {
|
||||
this.workspace = workspace;
|
||||
this.credentialsProvider = credentialsProvider;
|
||||
@@ -1236,25 +1244,38 @@ public class LocalResourceController extends BaseLocalResourceController {
|
||||
this.rootPath = RMUtils.getRootPath();
|
||||
this.userProjectsPath = RMUtils.getUserProjectsPath();
|
||||
this.sharedProjectsPath = RMUtils.getSharedProjectsPath();
|
||||
this.lockController = lockController;
|
||||
}
|
||||
|
||||
public Builder setRootPath(Path rootPath) {
|
||||
@NotNull
|
||||
public Builder setRootPath(@NotNull Path rootPath) {
|
||||
this.rootPath = rootPath;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setUserProjectsPath(Path userProjectsPath) {
|
||||
@NotNull
|
||||
public Builder setUserProjectsPath(@NotNull Path userProjectsPath) {
|
||||
this.userProjectsPath = userProjectsPath;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSharedProjectsPath(Path sharedProjectsPath) {
|
||||
@NotNull
|
||||
public Builder setSharedProjectsPath(@NotNull Path sharedProjectsPath) {
|
||||
this.sharedProjectsPath = sharedProjectsPath;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public LocalResourceController build() throws DBException {
|
||||
return new LocalResourceController(workspace, credentialsProvider, rootPath, userProjectsPath, sharedProjectsPath, smController);
|
||||
return new LocalResourceController(
|
||||
workspace,
|
||||
credentialsProvider,
|
||||
rootPath,
|
||||
userProjectsPath,
|
||||
sharedProjectsPath,
|
||||
smController,
|
||||
lockController
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-7
@@ -17,14 +17,15 @@
|
||||
package io.cloudbeaver.model.rm.local;
|
||||
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import io.cloudbeaver.utils.ServletAppUtils;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.app.DBPProject;
|
||||
import org.jkiss.dbeaver.model.data.json.JSONUtils;
|
||||
import org.jkiss.dbeaver.model.fs.lock.FileLockController;
|
||||
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.rm.RMProjectInfo;
|
||||
import org.jkiss.dbeaver.model.rm.RMProjectType;
|
||||
@@ -45,12 +46,12 @@ public class ProjectsMetadataInfo {
|
||||
|
||||
private final Map<String, RMProjectInfo> projectsInfo = new LinkedHashMap<>();
|
||||
private final Path projectsPath;
|
||||
private final FileLockController lockController;
|
||||
private final LockManager lockController;
|
||||
|
||||
|
||||
public ProjectsMetadataInfo(@NotNull Path projectsPath) throws DBException {
|
||||
public ProjectsMetadataInfo(@NotNull Path projectsPath, @NotNull LockManager lockController) throws DBException {
|
||||
this.projectsPath = projectsPath;
|
||||
this.lockController = new FileLockController(ServletAppUtils.getServletApplication().getApplicationInstanceId());
|
||||
this.lockController = lockController;
|
||||
readProjectInfos(projectsPath);
|
||||
}
|
||||
|
||||
@@ -139,7 +140,7 @@ public class ProjectsMetadataInfo {
|
||||
}
|
||||
|
||||
private void saveProjectsInfo() {
|
||||
try (var lock = lockController.lock(PROJECTS_INFO_FILE_NAME, "saveProjectsInfo")) {
|
||||
try (var lock = lockController.lock(LockTarget.of(PROJECTS_INFO_FILE_NAME), LockOptions.of("saveProjectsInfo"))) {
|
||||
log.info("Saving project information");
|
||||
Files.writeString(projectsPath.resolve(PROJECTS_INFO_FILE_NAME), JSONUtils.GSON.toJson(projectsInfo));
|
||||
} catch (IOException e) {
|
||||
@@ -148,4 +149,4 @@ public class ProjectsMetadataInfo {
|
||||
log.error("Error locking file " + PROJECTS_INFO_FILE_NAME + ": " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-6
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2024 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.
|
||||
@@ -75,13 +75,16 @@ public class CBApplicationCE extends CBApplication<CBServerConfig> {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public RMController createResourceController(@NotNull SMCredentialsProvider credentialsProvider,
|
||||
@NotNull DBPWorkspace workspace) throws DBException {
|
||||
return LocalResourceController.builder(credentialsProvider, workspace, this::getSecurityController).build();
|
||||
public RMController createResourceController(
|
||||
@NotNull SMCredentialsProvider credentialsProvider,
|
||||
@NotNull DBPWorkspace workspace
|
||||
) throws DBException {
|
||||
var lockManager = createLockManager();
|
||||
return LocalResourceController
|
||||
.builder(credentialsProvider, workspace, lockManager, this::getSecurityController)
|
||||
.build();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
Reference in New Issue
Block a user