diff --git a/server/bundles/graphql.config.yml b/server/bundles/graphql.config.yml
new file mode 100644
index 0000000000..9dd806b67e
--- /dev/null
+++ b/server/bundles/graphql.config.yml
@@ -0,0 +1,9 @@
+projects:
+ schema:
+ include: ./**/*.graphqls
+schema: "gql.ce"
+extensions:
+ endpoints:
+ Default GraphQL Endpoint:
+ url: http://localhost:8080/api/gql
+ introspect: false
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMNIOResourceFileStore.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMNIOResourceFileStore.java
deleted file mode 100644
index a4bc1d4c5c..0000000000
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMNIOResourceFileStore.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * DBeaver - Universal Database Manager
- * Copyright (C) 2010-2023 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.fs.nio;
-
-import org.jkiss.dbeaver.model.nio.NIOFileStore;
-import org.jkiss.dbeaver.model.rm.RMResource;
-
-import java.io.IOException;
-
-public class RMNIOResourceFileStore extends NIOFileStore {
- private final RMResource rmResource;
-
- public RMNIOResourceFileStore(RMResource rmResource) {
- this.rmResource = rmResource;
- }
-
- @Override
- public String name() {
- return rmResource.getName();
- }
-
- @Override
- public String type() {
- return "rmfs";
- }
-
- @Override
- public boolean isReadOnly() {
- return false;
- }
-
- @Override
- public long getTotalSpace() throws IOException {
- return rmResource.getLength();
- }
-}
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java
index 35e5827198..3dbe3c3b6e 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java
@@ -51,6 +51,7 @@ import org.jkiss.dbeaver.model.app.DBPProject;
import org.jkiss.dbeaver.model.auth.*;
import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration;
import org.jkiss.dbeaver.model.exec.DBCException;
+import org.jkiss.dbeaver.model.fs.DBFFileSystemManager;
import org.jkiss.dbeaver.model.meta.Association;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.model.navigator.DBNModel;
@@ -76,15 +77,15 @@ import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.dbeaver.runtime.jobs.DisconnectJob;
import org.jkiss.utils.CommonUtils;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
import java.lang.reflect.InvocationTargetException;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
/**
* Web session.
@@ -617,7 +618,6 @@ public class WebSession extends BaseWebSession
log.error("Error closing web session tokens");
}
this.userContext.setUser(null);
-
super.close();
}
@@ -901,7 +901,11 @@ public class WebSession extends BaseWebSession
// Auth credentials provider
// Adds auth properties passed from web (by user)
@Override
- public boolean provideAuthParameters(@NotNull DBRProgressMonitor monitor, @NotNull DBPDataSourceContainer dataSourceContainer, @NotNull DBPConnectionConfiguration configuration) {
+ public boolean provideAuthParameters(
+ @NotNull DBRProgressMonitor monitor,
+ @NotNull DBPDataSourceContainer dataSourceContainer,
+ @NotNull DBPConnectionConfiguration configuration
+ ) {
try {
// Properties from nested auth sessions
for (DBACredentialsProvider contextCredentialsProvider : getContextCredentialsProviders()) {
@@ -1019,6 +1023,9 @@ public class WebSession extends BaseWebSession
}
public void deleteSessionProject(@Nullable WebProjectImpl project) {
+ if (project != null) {
+ project.dispose();
+ }
getWorkspace().removeProject(project);
if (navigatorModel != null) {
navigatorModel.getRoot().removeProject(project);
@@ -1046,6 +1053,15 @@ public class WebSession extends BaseWebSession
}
}
+ @NotNull
+ public DBFFileSystemManager getFileSystemManager(String projectId) throws DBException {
+ var project = getProjectById(projectId);
+ if (project == null) {
+ throw new DBException("Project not found: " + projectId);
+ }
+ return project.getFileSystemManager();
+ }
+
private class SessionProgressMonitor extends BaseProgressMonitor {
@Override
public void beginTask(String name, int totalWork) {
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebUserContext.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebUserContext.java
index 36b70e0b8a..21725e7ef7 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebUserContext.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebUserContext.java
@@ -115,11 +115,7 @@ public class WebUserContext implements SMCredentialsProvider {
);
setRefreshToken(smRefreshToken);
setUserPermissions(smAuthPermissions.getPermissions());
- this.securityController = application.createSecurityController(this);
this.adminSecurityController = application.getAdminSecurityController(this);
- this.secretController = application.getSecretController(this);
- this.rmController = application.createResourceController(this, workspace);
- this.fileController = application.createFileController(this);
if (isSessionChanged) {
this.smSessionId = smAuthPermissions.getSessionId();
setUser(smAuthPermissions.getUserId() == null ? null : new WebUser(securityController.getCurrentUser()));
diff --git a/server/bundles/io.cloudbeaver.server/schema/schema.graphqls b/server/bundles/io.cloudbeaver.server/schema/schema.graphqls
index 873430e94e..afffe35fef 100644
--- a/server/bundles/io.cloudbeaver.server/schema/schema.graphqls
+++ b/server/bundles/io.cloudbeaver.server/schema/schema.graphqls
@@ -8,6 +8,8 @@ input PageInput {
offset: Int
}
+directive @since(version: String!) on OBJECT|SCALAR|QUERY|MUTATION|FIELD|VARIABLE_DEFINITION|OBJECT|FIELD_DEFINITION|ARGUMENT_DEFINITION|INTERFACE|ENUM|ENUM_VALUE|INPUT_OBJECT|INPUT_FIELD_DEFINITION
+
type Query
type Mutation
diff --git a/server/bundles/io.cloudbeaver.service.fs/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.service.fs/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..dcf8f1c8d1
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.fs/META-INF/MANIFEST.MF
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Vendor: DBeaver Corp
+Bundle-Name: Cloudbeaver Web Service - File System
+Bundle-SymbolicName: io.cloudbeaver.service.fs;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Release-Date: 20230904
+Bundle-RequiredExecutionEnvironment: JavaSE-11
+Bundle-ActivationPolicy: lazy
+Bundle-ClassPath: .
+Require-Bundle: io.cloudbeaver.server,
+ io.cloudbeaver.service.admin
+Automatic-Module-Name: io.cloudbeaver.service.fs
diff --git a/server/bundles/io.cloudbeaver.service.fs/build.properties b/server/bundles/io.cloudbeaver.service.fs/build.properties
new file mode 100644
index 0000000000..06be359875
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.fs/build.properties
@@ -0,0 +1,6 @@
+source.. = src/
+output.. = target/classes/
+bin.includes = .,\
+ META-INF/,\
+ schema/,\
+ plugin.xml
diff --git a/server/bundles/io.cloudbeaver.service.fs/plugin.xml b/server/bundles/io.cloudbeaver.service.fs/plugin.xml
new file mode 100644
index 0000000000..45540f23a6
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.fs/plugin.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/server/bundles/io.cloudbeaver.service.fs/pom.xml b/server/bundles/io.cloudbeaver.service.fs/pom.xml
new file mode 100644
index 0000000000..67e34d889a
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.fs/pom.xml
@@ -0,0 +1,16 @@
+
+
+ 4.0.0
+
+ io.cloudbeaver
+ bundles
+ 1.0.0-SNAPSHOT
+ ../
+
+ io.cloudbeaver.service.fs
+ 1.0.0-SNAPSHOT
+ eclipse-plugin
+
+
diff --git a/server/bundles/io.cloudbeaver.service.fs/schema/service.fs.graphqls b/server/bundles/io.cloudbeaver.service.fs/schema/service.fs.graphqls
new file mode 100644
index 0000000000..558d088c43
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.fs/schema/service.fs.graphqls
@@ -0,0 +1,34 @@
+type FSFile @since(version: "23.2.2") {
+ name: String!
+ length: Int!
+ folder: Boolean!
+ metaData: Object!
+}
+
+extend type Query @since(version: "23.2.2") {
+ fsListFileSystems(projectId: ID!): [String!]!
+
+ fsFile(projectId: ID!, fileURI: String!): FSFile!
+
+ fsListFiles(projectId: ID!, folderURI: String!): [FSFile!]!
+
+ # Reads file contents as string in UTF-8
+ fsReadFileContentAsString(projectId: ID!, fileURI: String!): String!
+}
+
+extend type Mutation @since(version: "23.2.2") {
+ fsCreateFile(projectId: ID!, fileURI:String!): FSFile!
+
+ fsCreateFolder(projectId: ID!, folderURI:String!): FSFile!
+
+ fsDeleteFile(projectId: ID!, fileURI:String!): Boolean!
+
+ fsMoveFile(projectId: ID!, fromURI: String!, toURI: String!): FSFile!
+
+ fsWriteFileStringContent(
+ projectId: ID!,
+ fileURI:String!,
+ data: String!,
+ forceOverwrite: Boolean!
+ ): Boolean!
+}
\ No newline at end of file
diff --git a/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/DBWServiceFS.java b/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/DBWServiceFS.java
new file mode 100644
index 0000000000..fefd6d1a09
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/DBWServiceFS.java
@@ -0,0 +1,90 @@
+/*
+ * DBeaver - Universal Database Manager
+ * Copyright (C) 2010-2023 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.service.fs;
+
+import io.cloudbeaver.DBWebException;
+import io.cloudbeaver.model.session.WebSession;
+import io.cloudbeaver.service.DBWService;
+import io.cloudbeaver.service.fs.model.FSFile;
+import org.jkiss.code.NotNull;
+
+import java.net.URI;
+
+/**
+ * Web service API
+ */
+public interface DBWServiceFS extends DBWService {
+ @NotNull
+ String[] getAvailableFileSystems(@NotNull WebSession webSession, @NotNull String projectId) throws DBWebException;
+
+ @NotNull
+ FSFile getFile(
+ @NotNull WebSession webSession,
+ @NotNull String projectId,
+ @NotNull URI fileURI
+ ) throws DBWebException;
+
+ @NotNull
+ FSFile[] getFiles(
+ @NotNull WebSession webSession,
+ @NotNull String projectId,
+ @NotNull URI folderURI
+ ) throws DBWebException;
+
+ @NotNull
+ String readFileContent(
+ @NotNull WebSession webSession,
+ @NotNull String projectId,
+ @NotNull URI fileURI
+ ) throws DBWebException;
+
+ boolean writeFileContent(
+ @NotNull WebSession webSession,
+ @NotNull String projectId,
+ @NotNull URI fileURI,
+ @NotNull String data,
+ boolean forceOverwrite
+ ) throws DBWebException;
+
+ @NotNull
+ FSFile createFile(
+ @NotNull WebSession webSession,
+ @NotNull String projectId,
+ @NotNull URI fileURI
+ ) throws DBWebException;
+
+ FSFile moveFile(
+ @NotNull WebSession webSession,
+ @NotNull String projectId,
+ @NotNull URI fromURI,
+ @NotNull URI toURI
+ ) throws DBWebException;
+
+ @NotNull
+ FSFile createFolder(
+ @NotNull WebSession webSession,
+ @NotNull String projectId,
+ @NotNull URI folderURI
+ ) throws DBWebException;
+
+ boolean deleteFile(
+ @NotNull WebSession webSession,
+ @NotNull String projectId,
+ @NotNull URI fileURI
+ ) throws DBWebException;
+
+}
diff --git a/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/WebServiceBindingFS.java b/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/WebServiceBindingFS.java
new file mode 100644
index 0000000000..4e0d92f056
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/WebServiceBindingFS.java
@@ -0,0 +1,91 @@
+/*
+ * DBeaver - Universal Database Manager
+ * Copyright (C) 2010-2023 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.service.fs;
+
+import io.cloudbeaver.DBWebException;
+import io.cloudbeaver.service.DBWBindingContext;
+import io.cloudbeaver.service.WebServiceBindingBase;
+import io.cloudbeaver.service.fs.impl.WebServiceFS;
+import org.jkiss.utils.CommonUtils;
+
+/**
+ * Web service implementation
+ */
+public class WebServiceBindingFS extends WebServiceBindingBase {
+
+ private static final String SCHEMA_FILE_NAME = "schema/service.fs.graphqls";
+
+ public WebServiceBindingFS() {
+ super(DBWServiceFS.class, new WebServiceFS(), SCHEMA_FILE_NAME);
+ }
+
+ @Override
+ public void bindWiring(DBWBindingContext model) throws DBWebException {
+ model.getQueryType()
+ .dataFetcher("fsListFileSystems",
+ env -> getService(env).getAvailableFileSystems(getWebSession(env), env.getArgument("projectId")))
+ .dataFetcher("fsFile",
+ env -> getService(env).getFile(getWebSession(env),
+ env.getArgument("projectId"),
+ env.getArgument("fileURI"))
+ )
+ .dataFetcher("fsListFiles",
+ env -> getService(env).getFiles(getWebSession(env),
+ env.getArgument("projectId"),
+ env.getArgument("folderURI"))
+ )
+ .dataFetcher("fsReadFileContentAsString",
+ env -> getService(env).readFileContent(getWebSession(env),
+ env.getArgument("projectId"),
+ env.getArgument("fileURI"))
+ )
+ ;
+ model.getMutationType()
+ .dataFetcher("fsCreateFile",
+ env -> getService(env).createFile(getWebSession(env),
+ env.getArgument("projectId"),
+ env.getArgument("fileURI"))
+ )
+ .dataFetcher("fsCreateFolder",
+ env -> getService(env).createFolder(getWebSession(env),
+ env.getArgument("projectId"),
+ env.getArgument("folderURI"))
+ )
+ .dataFetcher("fsDeleteFile",
+ env -> getService(env).deleteFile(getWebSession(env),
+ env.getArgument("projectId"),
+ env.getArgument("fileURI"))
+ )
+ .dataFetcher("fsMoveFile",
+ env -> getService(env).moveFile(
+ getWebSession(env),
+ env.getArgument("projectId"),
+ env.getArgument("fromURI"),
+ env.getArgument("toURI"))
+ )
+ .dataFetcher("fsWriteFileStringContent",
+ env -> getService(env).writeFileContent(
+ getWebSession(env),
+ env.getArgument("projectId"),
+ env.getArgument("fileURI"),
+ env.getArgument("data"),
+ CommonUtils.toBoolean(env.getArgument("forceOverwrite"))
+ )
+ )
+ ;
+ }
+}
diff --git a/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/impl/WebServiceFS.java b/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/impl/WebServiceFS.java
new file mode 100644
index 0000000000..2acfa3e0c4
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/impl/WebServiceFS.java
@@ -0,0 +1,174 @@
+/*
+ * DBeaver - Universal Database Manager
+ * Copyright (C) 2010-2023 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.service.fs.impl;
+
+import io.cloudbeaver.DBWebException;
+import io.cloudbeaver.model.session.WebSession;
+import io.cloudbeaver.service.fs.DBWServiceFS;
+import io.cloudbeaver.service.fs.model.FSFile;
+import org.jkiss.code.NotNull;
+import org.jkiss.dbeaver.DBException;
+import org.jkiss.dbeaver.model.fs.DBFVirtualFileSystem;
+
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+/**
+ * Web file system implementation
+ */
+public class WebServiceFS implements DBWServiceFS {
+
+ @NotNull
+ @Override
+ public String[] getAvailableFileSystems(@NotNull WebSession webSession, @NotNull String projectId)
+ throws DBWebException {
+ try {
+ return webSession.getFileSystemManager(projectId)
+ .getVirtualFileSystems()
+ .stream()
+ .map(DBFVirtualFileSystem::getType)
+ .toArray(String[]::new);
+ } catch (Exception e) {
+ throw new DBWebException("Failed to load file systems: " + e.getMessage(), e);
+ }
+ }
+
+ @NotNull
+ @Override
+ public FSFile getFile(@NotNull WebSession webSession, @NotNull String projectId, @NotNull URI fileUri)
+ throws DBWebException {
+ try {
+ Path filePath = webSession.getFileSystemManager(projectId).of(webSession.getProgressMonitor(), fileUri);
+ return new FSFile(filePath);
+ } catch (Exception e) {
+ throw new DBWebException("Failed to found file: " + e.getMessage(), e);
+ }
+ }
+
+ @NotNull
+ @Override
+ public FSFile[] getFiles(@NotNull WebSession webSession, @NotNull String projectId, @NotNull URI folderURI)
+ throws DBWebException {
+ try {
+ Path folderPath = webSession.getFileSystemManager(projectId).of(webSession.getProgressMonitor(), folderURI);
+ try (var filesStream = Files.list(folderPath)) {
+ return filesStream.map(FSFile::new)
+ .toArray(FSFile[]::new);
+ }
+ } catch (Exception e) {
+ throw new DBWebException("Failed to list files: " + e.getMessage(), e);
+ }
+ }
+
+ @NotNull
+ @Override
+ public String readFileContent(@NotNull WebSession webSession, @NotNull String projectId, @NotNull URI fileUri)
+ throws DBWebException {
+ try {
+ Path filePath = webSession.getFileSystemManager(projectId).of(webSession.getProgressMonitor(), fileUri);
+ return Files.readString(filePath);
+ } catch (Exception e) {
+ throw new DBWebException("Failed to read file content: " + e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public boolean writeFileContent(
+ @NotNull WebSession webSession,
+ @NotNull String projectId,
+ @NotNull URI fileURI,
+ @NotNull String data,
+ boolean forceOverwrite
+ )
+ throws DBWebException {
+ try {
+ Path filePath = webSession.getFileSystemManager(projectId).of(webSession.getProgressMonitor(), fileURI);
+ if (!forceOverwrite && Files.exists(filePath)) {
+ throw new DBException("Cannot overwrite exist file");
+ }
+ Files.writeString(filePath, data);
+ return true;
+ } catch (Exception e) {
+ throw new DBWebException("Failed to write file content: " + e.getMessage(), e);
+ }
+ }
+
+ @NotNull
+ @Override
+ public FSFile createFile(
+ @NotNull WebSession webSession,
+ @NotNull String projectId,
+ @NotNull URI fileUri
+ ) throws DBWebException {
+ try {
+ Path filePath = webSession.getFileSystemManager(projectId).of(webSession.getProgressMonitor(), fileUri);
+ Files.createFile(filePath);
+ return new FSFile(filePath);
+ } catch (Exception e) {
+ throw new DBWebException("Failed to create file: " + e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public FSFile moveFile(
+ @NotNull WebSession webSession,
+ @NotNull String projectId,
+ @NotNull URI fromURI,
+ @NotNull URI toURI
+ ) throws DBWebException {
+ try {
+ Path from = webSession.getFileSystemManager(projectId).of(webSession.getProgressMonitor(), fromURI);
+ Path to = webSession.getFileSystemManager(projectId).of(webSession.getProgressMonitor(), toURI);
+ Files.move(from, to);
+ return new FSFile(to);
+ } catch (Exception e) {
+ throw new DBWebException("Failed to move file: " + e.getMessage(), e);
+ }
+ }
+
+ @NotNull
+ @Override
+ public FSFile createFolder(
+ @NotNull WebSession webSession,
+ @NotNull String projectId,
+ @NotNull URI folderURI
+ ) throws DBWebException {
+ try {
+ Path folderPath = webSession.getFileSystemManager(projectId).of(webSession.getProgressMonitor(), folderURI);
+ Files.createDirectory(folderPath);
+ return new FSFile(folderPath);
+ } catch (Exception e) {
+ throw new DBWebException("Failed to create folder: " + e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public boolean deleteFile(
+ @NotNull WebSession webSession,
+ @NotNull String projectId,
+ @NotNull URI fileUri
+ ) throws DBWebException {
+ try {
+ Path filePath = webSession.getFileSystemManager(projectId).of(webSession.getProgressMonitor(), fileUri);
+ Files.delete(filePath);
+ return true;
+ } catch (Exception e) {
+ throw new DBWebException("Failed to create folder: " + e.getMessage(), e);
+ }
+ }
+}
diff --git a/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/model/FSFile.java b/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/model/FSFile.java
new file mode 100644
index 0000000000..757a956f52
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/model/FSFile.java
@@ -0,0 +1,59 @@
+/*
+ * DBeaver - Universal Database Manager
+ * Copyright (C) 2010-2023 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.service.fs.model;
+
+import org.jkiss.dbeaver.model.meta.Property;
+import org.jkiss.utils.ArrayUtils;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Map;
+
+public class FSFile {
+ private final Path path;
+
+ public FSFile(Path path) {
+ this.path = path;
+ }
+
+ @Property
+ public String getName() {
+ String[] pathParts = path.getFileName().toString().split(path.getFileSystem().getSeparator());
+ if (ArrayUtils.isEmpty(pathParts)) {
+ return "";
+ }
+ return pathParts[pathParts.length - 1];
+ }
+
+ @Property
+
+ public long getLength() throws IOException {
+ return Files.size(path);
+ }
+
+ @Property
+
+ public boolean isFolder() {
+ return Files.isDirectory(path);
+ }
+
+ @Property
+ public Map getMetaData() {
+ return Map.of();
+ }
+}
diff --git a/server/bundles/io.cloudbeaver.service.rm.nio/META-INF/MANIFEST.MF b/server/bundles/io.cloudbeaver.service.rm.nio/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..25d8f12537
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.rm.nio/META-INF/MANIFEST.MF
@@ -0,0 +1,16 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Vendor: DBeaver Corp
+Bundle-Name: Cloudbeaver Resource manager NIO implementation
+Bundle-SymbolicName: io.cloudbeaver.service.rm.nio;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Release-Date: 20230927
+Bundle-RequiredExecutionEnvironment: JavaSE-11
+Bundle-ActivationPolicy: lazy
+Bundle-ClassPath: .
+Require-Bundle: io.cloudbeaver.model,
+ org.jkiss.dbeaver.model,
+ org.jkiss.dbeaver.model.nio
+Export-Package: io.cloudbeaver.service.rm.nio,
+ io.cloudbeaver.service.rm.fs
+Automatic-Module-Name: io.cloudbeaver.service.rm.nio
diff --git a/server/bundles/io.cloudbeaver.service.rm.nio/build.properties b/server/bundles/io.cloudbeaver.service.rm.nio/build.properties
new file mode 100644
index 0000000000..0511fdeb94
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.rm.nio/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = target/classes/
+bin.includes = .,\
+ META-INF/,\
+ plugin.xml
diff --git a/server/bundles/io.cloudbeaver.service.rm.nio/plugin.xml b/server/bundles/io.cloudbeaver.service.rm.nio/plugin.xml
new file mode 100644
index 0000000000..d6694efc2c
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.rm.nio/plugin.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/server/bundles/io.cloudbeaver.service.rm.nio/pom.xml b/server/bundles/io.cloudbeaver.service.rm.nio/pom.xml
new file mode 100644
index 0000000000..2aefd764ac
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.rm.nio/pom.xml
@@ -0,0 +1,16 @@
+
+
+ 4.0.0
+
+ io.cloudbeaver
+ bundles
+ 1.0.0-SNAPSHOT
+ ../
+
+ io.cloudbeaver.service.rm.nio
+ 1.0.0-SNAPSHOT
+ eclipse-plugin
+
+
diff --git a/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/fs/RMVirtualFileSystem.java b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/fs/RMVirtualFileSystem.java
new file mode 100644
index 0000000000..49b68bfd67
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/fs/RMVirtualFileSystem.java
@@ -0,0 +1,81 @@
+/*
+ * DBeaver - Universal Database Manager
+ * Copyright (C) 2010-2023 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.service.rm.fs;
+
+import io.cloudbeaver.model.session.WebSession;
+import io.cloudbeaver.service.rm.nio.RMNIOFileSystemProvider;
+import org.jkiss.code.NotNull;
+import org.jkiss.dbeaver.DBException;
+import org.jkiss.dbeaver.model.DBPImage;
+import org.jkiss.dbeaver.model.fs.DBFVirtualFileSystem;
+import org.jkiss.dbeaver.model.fs.DBFVirtualFileSystemRoot;
+import org.jkiss.dbeaver.model.rm.RMProject;
+import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
+
+import java.net.URI;
+import java.nio.file.Path;
+
+public class RMVirtualFileSystem implements DBFVirtualFileSystem {
+ @NotNull
+ private final RMNIOFileSystemProvider rmNioFileSystemProvider;
+
+ @NotNull
+ private final RMProject rmProject;
+ public RMVirtualFileSystem(@NotNull WebSession webSession, @NotNull RMProject rmProject) {
+ this.rmNioFileSystemProvider = new RMNIOFileSystemProvider(webSession.getRmController());
+ this.rmProject = rmProject;
+ }
+
+ @NotNull
+ @Override
+ public String getFileSystemDisplayName() {
+ return "RM";
+ }
+
+ @NotNull
+ @Override
+ public String getType() {
+ return "rm";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Resource Manager file system";
+ }
+
+ @Override
+ public DBPImage getIcon() {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public String getId() {
+ return rmProject.getId();
+ }
+
+ @Override
+ public Path getPathByURI(DBRProgressMonitor monitor, URI uri) {
+ return rmNioFileSystemProvider.getPath(uri);
+ }
+
+ @NotNull
+ @Override
+ public DBFVirtualFileSystemRoot[] getRootFolders(DBRProgressMonitor monitor) throws DBException {
+ return new RMVirtualFileSystemRoot[]{new RMVirtualFileSystemRoot(this, rmProject, rmNioFileSystemProvider)};
+ }
+}
diff --git a/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/fs/RMVirtualFileSystemProvider.java b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/fs/RMVirtualFileSystemProvider.java
new file mode 100644
index 0000000000..e5355ee310
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/fs/RMVirtualFileSystemProvider.java
@@ -0,0 +1,48 @@
+/*
+ * DBeaver - Universal Database Manager
+ * Copyright (C) 2010-2023 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.service.rm.fs;
+
+import io.cloudbeaver.WebProjectImpl;
+import io.cloudbeaver.model.session.WebSession;
+import org.jkiss.code.NotNull;
+import org.jkiss.dbeaver.Log;
+import org.jkiss.dbeaver.model.app.DBPProject;
+import org.jkiss.dbeaver.model.fs.DBFFileSystemProvider;
+import org.jkiss.dbeaver.model.fs.DBFVirtualFileSystem;
+import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
+
+public class RMVirtualFileSystemProvider implements DBFFileSystemProvider {
+ private static final Log log = Log.getLog(RMVirtualFileSystemProvider.class);
+
+ @Override
+ public DBFVirtualFileSystem[] getAvailableFileSystems(
+ @NotNull DBRProgressMonitor monitor,
+ @NotNull DBPProject project
+ ) {
+ var session = project.getSessionContext().getPrimaryAuthSpace();
+ if (!(session instanceof WebSession)) {
+ return new DBFVirtualFileSystem[0];
+ }
+ WebSession webSession = (WebSession) session;
+ WebProjectImpl webProject = webSession.getProjectById(project.getId());
+ if (webProject == null) {
+ log.warn(String.format("Project %s not found in session %s", project.getId(), webSession.getSessionId()));
+ return new DBFVirtualFileSystem[0];
+ }
+ return new DBFVirtualFileSystem[]{new RMVirtualFileSystem(webSession, webProject.getRmProject())};
+ }
+}
diff --git a/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/fs/RMVirtualFileSystemRoot.java b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/fs/RMVirtualFileSystemRoot.java
new file mode 100644
index 0000000000..10f9ad6d9b
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/fs/RMVirtualFileSystemRoot.java
@@ -0,0 +1,77 @@
+/*
+ * DBeaver - Universal Database Manager
+ * Copyright (C) 2010-2023 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.service.rm.fs;
+
+import io.cloudbeaver.service.rm.nio.RMNIOFileSystemProvider;
+import io.cloudbeaver.service.rm.nio.RMNIOFileSystem;
+import io.cloudbeaver.service.rm.nio.RMPath;
+import org.jkiss.code.NotNull;
+import org.jkiss.dbeaver.model.DBPImage;
+import org.jkiss.dbeaver.model.fs.DBFVirtualFileSystem;
+import org.jkiss.dbeaver.model.fs.DBFVirtualFileSystemRoot;
+import org.jkiss.dbeaver.model.rm.RMProject;
+import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
+
+import java.nio.file.Path;
+
+public class RMVirtualFileSystemRoot implements DBFVirtualFileSystemRoot {
+ @NotNull
+ private final RMVirtualFileSystem rmFileSystem;
+ @NotNull
+ private final RMProject rmProject;
+ @NotNull
+ private final RMNIOFileSystemProvider rmNioFileSystemProvider;
+
+ public RMVirtualFileSystemRoot(
+ @NotNull RMVirtualFileSystem rmFileSystem,
+ @NotNull RMProject rmProject,
+ @NotNull RMNIOFileSystemProvider rmNioFileSystemProvider
+ ) {
+ this.rmFileSystem = rmFileSystem;
+ this.rmProject = rmProject;
+ this.rmNioFileSystemProvider = rmNioFileSystemProvider;
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return rmProject.getName();
+ }
+
+ @NotNull
+ @Override
+ public DBFVirtualFileSystem getFileSystem() {
+ return rmFileSystem;
+ }
+
+ @NotNull
+ @Override
+ public String getRootId() {
+ return rmProject.getId();
+ }
+
+ @Override
+ public DBPImage getRootIcon() {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public Path getRootPath(DBRProgressMonitor monitor) {
+ return new RMPath(new RMNIOFileSystem(rmProject.getId(), rmNioFileSystemProvider));
+ }
+}
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMByteArrayChannel.java b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMByteArrayChannel.java
similarity index 98%
rename from server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMByteArrayChannel.java
rename to server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMByteArrayChannel.java
index d0f6913f7f..9d51f07a57 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMByteArrayChannel.java
+++ b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMByteArrayChannel.java
@@ -23,7 +23,7 @@
* questions.
*/
-package io.cloudbeaver.model.rm.fs.nio;
+package io.cloudbeaver.service.rm.nio;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.nio.ByteArrayChannel;
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMNIOFileSystem.java b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMNIOFileSystem.java
similarity index 93%
rename from server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMNIOFileSystem.java
rename to server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMNIOFileSystem.java
index 0abc646d75..f0ed593597 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMNIOFileSystem.java
+++ b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMNIOFileSystem.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package io.cloudbeaver.model.rm.fs.nio;
+package io.cloudbeaver.service.rm.nio;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
@@ -41,19 +41,15 @@ public class RMNIOFileSystem extends NIOFileSystem {
// null for root 'rm://' path
private final String rmProjectId;
@NotNull
- private final RMController rmController;
- @NotNull
private final RMNIOFileSystemProvider rmNioFileSystemProvider;
@Nullable
private RMProject rmProject;
public RMNIOFileSystem(
@Nullable String rmProjectId,
- @NotNull RMController rmController,
@NotNull RMNIOFileSystemProvider rmNioFileSystemProvider
) {
this.rmProjectId = rmProjectId;
- this.rmController = rmController;
this.rmNioFileSystemProvider = rmNioFileSystemProvider;
}
@@ -119,7 +115,7 @@ public class RMNIOFileSystem extends NIOFileSystem {
@NotNull
public RMController getRmController() {
- return rmController;
+ return rmNioFileSystemProvider.getRmController();
}
@Nullable
@@ -136,7 +132,7 @@ public class RMNIOFileSystem extends NIOFileSystem {
throw new IOException("Project id not specified");
}
try {
- RMProject project = rmController.getProject(rmProjectId, false, false);
+ RMProject project = getRmController().getProject(rmProjectId, false, false);
if (project == null) {
throw new FileNotFoundException("Project not exist: " + rmProjectId);
}
@@ -146,4 +142,8 @@ public class RMNIOFileSystem extends NIOFileSystem {
throw new IOException("Failed to get project:" + e.getMessage(), e);
}
}
+
+ public RMNIOFileSystemProvider rmProvider() {
+ return rmNioFileSystemProvider;
+ }
}
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMNIOFileSystemProvider.java b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMNIOFileSystemProvider.java
similarity index 88%
rename from server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMNIOFileSystemProvider.java
rename to server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMNIOFileSystemProvider.java
index e87da418fa..676b28dddc 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMNIOFileSystemProvider.java
+++ b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMNIOFileSystemProvider.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package io.cloudbeaver.model.rm.fs.nio;
+package io.cloudbeaver.service.rm.nio;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
@@ -53,8 +53,8 @@ public class RMNIOFileSystemProvider extends NIOFileSystemProvider {
}
@Override
- public FileSystem newFileSystem(URI uri, Map env) throws IOException {
- throw new FileAlreadyExistsException("RM file system already exist");
+ public FileSystem newFileSystem(URI uri, Map env) {
+ return getFileSystem(uri);
}
@Override
@@ -65,7 +65,7 @@ public class RMNIOFileSystemProvider extends NIOFileSystemProvider {
projectId = null;
}
try {
- return new RMNIOFileSystem(projectId, rmController, this);
+ return new RMNIOFileSystem(projectId, this);
} catch (Exception e) {
throw new FileSystemNotFoundException("RM file system not found: " + e.getMessage());
}
@@ -78,7 +78,7 @@ public class RMNIOFileSystemProvider extends NIOFileSystemProvider {
if (CommonUtils.isEmpty(projectId)) {
projectId = null;
}
- RMNIOFileSystem rmNioFileSystem = new RMNIOFileSystem(projectId, rmController, this);
+ RMNIOFileSystem rmNioFileSystem = new RMNIOFileSystem(projectId, this);
String resourcePath = uri.getPath();
if (CommonUtils.isNotEmpty(resourcePath) && projectId == null) {
throw new IllegalArgumentException("Project is not specified in URI");
@@ -91,10 +91,11 @@ public class RMNIOFileSystemProvider extends NIOFileSystemProvider {
}
@Override
- public RMByteArrayChannel newByteChannel(Path path, Set extends OpenOption> options, FileAttribute>... attrs) throws IOException {
+ public RMByteArrayChannel newByteChannel(Path path, Set extends OpenOption> options, FileAttribute>... attrs)
+ throws IOException {
RMPath rmPath = (RMPath) path;
- if (rmPath.isProjectPath()) {
- throw new IllegalArgumentException("Cannot open channel for the project");
+ if (Files.isDirectory(rmPath)) {
+ throw new IllegalArgumentException("Cannot open channel for a folder");
}
try {
@@ -115,7 +116,8 @@ public class RMNIOFileSystemProvider extends NIOFileSystemProvider {
}
@Override
- public DirectoryStream newDirectoryStream(Path dir, DirectoryStream.Filter super Path> filter) throws IOException {
+ public DirectoryStream newDirectoryStream(Path dir, DirectoryStream.Filter super Path> filter)
+ throws IOException {
RMPath rmDir = (RMPath) dir;
String rmDirPath = rmDir.getResourcePath();
String separator = rmDir.getFileSystem().getSeparator();
@@ -130,7 +132,6 @@ public class RMNIOFileSystemProvider extends NIOFileSystemProvider {
.map(rmProject -> (Path) new RMPath(
new RMNIOFileSystem(
rmProject.getId(),
- rmController,
RMNIOFileSystemProvider.this
)
)
@@ -166,6 +167,9 @@ public class RMNIOFileSystemProvider extends NIOFileSystemProvider {
public void createDirectory(Path dir, FileAttribute>... attrs) throws IOException {
RMPath rmDir = (RMPath) dir;
try {
+ if (rmDir.isRmRootPath()) {
+ return;
+ }
if (rmDir.isProjectPath()) {
rmController.createProject(RMUtils.getProjectName(rmDir.getRmProjectId()), null);
} else {
@@ -180,7 +184,7 @@ public class RMNIOFileSystemProvider extends NIOFileSystemProvider {
public void delete(Path path) throws IOException {
RMPath rmPath = (RMPath) path;
if (rmPath.isRmRootPath()) {
- throw new IOException("Can not delete root rm directory");
+ throw new IOException("Cannot delete root rm dir:" + path);
}
try {
String rmProjectId = rmPath.getRmProjectId();
@@ -205,7 +209,9 @@ public class RMNIOFileSystemProvider extends NIOFileSystemProvider {
RMPath rmSource = (RMPath) source;
RMPath rmTarget = (RMPath) target;
try {
- rmController.moveResource(rmSource.getRmProjectId(), rmSource.getResourcePath(), rmTarget.getResourcePath());
+ rmController.moveResource(rmSource.getRmProjectId(),
+ rmSource.getResourcePath(),
+ rmTarget.getResourcePath());
} catch (DBException e) {
throw new IOException("Failed to move rm resource: " + e.getMessage(), e);
}
@@ -225,25 +231,19 @@ public class RMNIOFileSystemProvider extends NIOFileSystemProvider {
@Override
public FileStore getFileStore(Path path) throws IOException {
RMPath rmPath = (RMPath) path;
- if (rmPath.isProjectPath()) {
- return new RMNIOProjectFileStore(rmPath.getFileSystem().getRmProject());
- } else {
- try {
- RMResource rmResource = rmController.getResource(rmPath.getRmProjectId(), rmPath.getResourcePath());
- if (rmResource == null) {
- throw new FileNotFoundException();
- }
- return new RMNIOResourceFileStore(rmResource);
- } catch (DBException e) {
- throw new IOException("Failed to ");
- }
+ if (rmPath.isRmRootPath()) {
+ throw new IllegalArgumentException("Cannot create file store for path: " + path);
}
+ return new RMNIOProjectFileStore(rmPath.getFileSystem().getRmProject());
}
@Override
public void checkAccess(Path path, AccessMode... modes) throws IOException {
RMPath rmPath = (RMPath) path;
try {
+ if (rmPath.isRmRootPath()) {
+ return;
+ }
if (rmPath.isProjectPath()) {
if (rmController.getProject(rmPath.getRmProjectId(), false, false) == null) {
// we should throw error, otherwise Files.exists return true
@@ -272,8 +272,8 @@ public class RMNIOFileSystemProvider extends NIOFileSystemProvider {
return type.cast(new RMRootBasicAttribute());
}
if (rmPath.isProjectPath()) {
- boolean projectNotExist = rmController.getProject(rmPath.getRmProjectId(), false, false) == null;
- if (projectNotExist) {
+ boolean projectExist = rmController.getProject(rmPath.getRmProjectId(), false, false) != null;
+ if (!projectExist) {
throw new FileNotFoundException();
}
return type.cast(new RMRootBasicAttribute());
@@ -290,4 +290,9 @@ public class RMNIOFileSystemProvider extends NIOFileSystemProvider {
}
return null;
}
+
+ @NotNull
+ public RMController getRmController() {
+ return rmController;
+ }
}
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMNIOProjectFileStore.java b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMNIOProjectFileStore.java
similarity index 97%
rename from server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMNIOProjectFileStore.java
rename to server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMNIOProjectFileStore.java
index da1bd715f8..2e08f5f0a8 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMNIOProjectFileStore.java
+++ b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMNIOProjectFileStore.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package io.cloudbeaver.model.rm.fs.nio;
+package io.cloudbeaver.service.rm.nio;
import org.jkiss.dbeaver.model.nio.NIOFileStore;
import org.jkiss.dbeaver.model.rm.RMProject;
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMOutputStream.java b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMOutputStream.java
similarity index 97%
rename from server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMOutputStream.java
rename to server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMOutputStream.java
index 09fee299e9..4db2a79a69 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMOutputStream.java
+++ b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMOutputStream.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package io.cloudbeaver.model.rm.fs.nio;
+package io.cloudbeaver.service.rm.nio;
import org.jkiss.dbeaver.DBException;
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMPath.java b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMPath.java
similarity index 92%
rename from server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMPath.java
rename to server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMPath.java
index a1e9a49c37..c38642269e 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMPath.java
+++ b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMPath.java
@@ -14,12 +14,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package io.cloudbeaver.model.rm.fs.nio;
+package io.cloudbeaver.service.rm.nio;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.nio.NIOPath;
+import org.jkiss.utils.ArrayUtils;
import org.jkiss.utils.CommonUtils;
import java.io.IOException;
@@ -58,7 +59,7 @@ public class RMPath extends NIOPath {
@Override
public Path getRoot() {
- if (isProjectPath()) {
+ if (isProjectPath() || isRmRootPath()) {
return null;
}
return new RMPath(rmNioFileSystem);
@@ -66,13 +67,16 @@ public class RMPath extends NIOPath {
@Override
public Path getFileName() {
- return this;
+ var parts = pathParts();
+ if (ArrayUtils.isEmpty(parts)) {
+ return this;
+ }
+ return new RMPath(rmNioFileSystem, parts[parts.length - 1]);
}
@Override
public Path getParent() {
- // project is root and have no parent
- if (isProjectPath()) {
+ if (isRmRootPath() || isProjectPath()) {
return null;
}
@@ -90,14 +94,6 @@ public class RMPath extends NIOPath {
return pathParts().length;
}
- @Override
- public boolean startsWith(@NotNull Path other) {
- if (!(other instanceof RMPath)) {
- return false;
- }
- return toString().startsWith(other.toString());
- }
-
@Override
public Path normalize() {
return this;
@@ -127,8 +123,11 @@ public class RMPath extends NIOPath {
public URI toUri() {
var fileSystem = getFileSystem();
var uriBuilder = new StringBuilder(fileSystem.provider().getScheme())
- .append("://")
- .append(rmProjectId);
+ .append("://");
+
+ if (rmProjectId != null) {
+ uriBuilder.append(rmProjectId);
+ }
String rmResourcePath = getResourcePath();
if (rmResourcePath != null) {
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMResourceBasicAttribute.java b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMResourceBasicAttribute.java
similarity index 97%
rename from server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMResourceBasicAttribute.java
rename to server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMResourceBasicAttribute.java
index 2387e3e07e..cff20b301c 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMResourceBasicAttribute.java
+++ b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMResourceBasicAttribute.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package io.cloudbeaver.model.rm.fs.nio;
+package io.cloudbeaver.service.rm.nio;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.model.nio.NIOFileBasicAttribute;
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMRootBasicAttribute.java b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMRootBasicAttribute.java
similarity index 96%
rename from server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMRootBasicAttribute.java
rename to server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMRootBasicAttribute.java
index 5ce279ae3f..7cb22e8123 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/fs/nio/RMRootBasicAttribute.java
+++ b/server/bundles/io.cloudbeaver.service.rm.nio/src/io/cloudbeaver/service/rm/nio/RMRootBasicAttribute.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package io.cloudbeaver.model.rm.fs.nio;
+package io.cloudbeaver.service.rm.nio;
import org.jkiss.dbeaver.model.nio.NIOFileBasicAttribute;
diff --git a/server/bundles/io.cloudbeaver.service.rm/schema/service.rm.graphqls b/server/bundles/io.cloudbeaver.service.rm/schema/service.rm.graphqls
index a3797f5a70..79589bb1fa 100644
--- a/server/bundles/io.cloudbeaver.service.rm/schema/service.rm.graphqls
+++ b/server/bundles/io.cloudbeaver.service.rm/schema/service.rm.graphqls
@@ -34,6 +34,7 @@ input RMSubjectProjectPermissions {
permissions: [String!]!
}
+
input RMProjectPermissions {
projectId: String!
permissions: [String!]!
@@ -59,42 +60,41 @@ extend type Query {
folder: String,
nameMask: String,
readProperties: Boolean,
- readHistory: Boolean): [RMResource!]!
+ readHistory: Boolean): [RMResource!]! @deprecated
# Reads resource contents as string in UTF-8
rmReadResourceAsString(
projectId: String!,
- resourcePath: String!): String!
+ resourcePath: String!): String! @deprecated
}
extend type Mutation {
-
rmCreateResource(
projectId: String!,
resourcePath: String!,
- isFolder: Boolean!): String!
+ isFolder: Boolean!): String! @deprecated
rmMoveResource(
projectId: String!,
oldResourcePath: String!,
- newResourcePath: String): String!
+ newResourcePath: String): String! @deprecated
rmDeleteResource(
projectId: String!,
resourcePath: String!,
- recursive: Boolean!): Boolean
+ recursive: Boolean!): Boolean @deprecated
rmWriteResourceStringContent(
projectId: String!,
resourcePath: String!,
data: String!,
- forceOverwrite: Boolean!): String!
+ forceOverwrite: Boolean!): String! @deprecated
rmCreateProject(
projectId: ID,
projectName: String!,
- description: String): RMProject!
+ description: String): RMProject! @deprecated
rmDeleteProject(projectId: ID!): Boolean!
diff --git a/server/bundles/pom.xml b/server/bundles/pom.xml
index 0926706826..453987399b 100644
--- a/server/bundles/pom.xml
+++ b/server/bundles/pom.xml
@@ -19,7 +19,9 @@
io.cloudbeaver.service.admin
io.cloudbeaver.service.auth
io.cloudbeaver.service.metadata
+ io.cloudbeaver.service.fs
io.cloudbeaver.service.rm
+ io.cloudbeaver.service.rm.nio
io.cloudbeaver.service.data.transfer
io.cloudbeaver.service.security
diff --git a/server/features/io.cloudbeaver.server.feature/feature.xml b/server/features/io.cloudbeaver.server.feature/feature.xml
index 513cd1aeb8..3be4b73b5b 100644
--- a/server/features/io.cloudbeaver.server.feature/feature.xml
+++ b/server/features/io.cloudbeaver.server.feature/feature.xml
@@ -36,7 +36,9 @@
+
+
diff --git a/server/test/io.cloudbeaver.test.platform/META-INF/MANIFEST.MF b/server/test/io.cloudbeaver.test.platform/META-INF/MANIFEST.MF
index b66eb7fdf3..55384ba6ab 100644
--- a/server/test/io.cloudbeaver.test.platform/META-INF/MANIFEST.MF
+++ b/server/test/io.cloudbeaver.test.platform/META-INF/MANIFEST.MF
@@ -24,5 +24,6 @@ Require-Bundle: org.eclipse.core.runtime,
io.cloudbeaver.resources.drivers.base,
io.cloudbeaver.product.ce,
io.cloudbeaver.service.auth,
- io.cloudbeaver.service.rm
+ io.cloudbeaver.service.rm,
+ io.cloudbeaver.service.rm.nio
Export-Package: io.cloudbeaver.test.platform
diff --git a/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/model/rm/RMNIOTest.java b/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/model/rm/RMNIOTest.java
index 7aeb0c9f6d..80ca252be3 100644
--- a/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/model/rm/RMNIOTest.java
+++ b/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/model/rm/RMNIOTest.java
@@ -16,11 +16,11 @@
*/
package io.cloudbeaver.model.rm;
-import io.cloudbeaver.model.rm.fs.nio.RMNIOFileSystem;
-import io.cloudbeaver.model.rm.fs.nio.RMNIOFileSystemProvider;
-import io.cloudbeaver.model.rm.fs.nio.RMPath;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.server.CBConstants;
+import io.cloudbeaver.service.rm.nio.RMNIOFileSystem;
+import io.cloudbeaver.service.rm.nio.RMNIOFileSystemProvider;
+import io.cloudbeaver.service.rm.nio.RMPath;
import io.cloudbeaver.test.platform.CEServerTestSuite;
import io.cloudbeaver.utils.WebTestUtils;
import org.jkiss.dbeaver.DBException;
@@ -96,7 +96,7 @@ public class RMNIOTest {
@Test
public void testNotExistProject() {
- RMPath notExistPath = new RMPath(new RMNIOFileSystem("s_not_exist", webSession.getRmController(), rmFsProvider));
+ RMPath notExistPath = new RMPath(new RMNIOFileSystem("s_not_exist", rmFsProvider));
Assert.assertFalse(Files.exists(notExistPath));
}
@@ -105,7 +105,7 @@ public class RMNIOTest {
var randomName = SecurityUtils.generateUniqueId();
String randomProject = "s_random_project_" + randomName;
- RMPath newProjectPath = new RMPath(new RMNIOFileSystem(randomProject, webSession.getRmController(), rmFsProvider));
+ RMPath newProjectPath = new RMPath(new RMNIOFileSystem(randomProject, rmFsProvider));
Assert.assertFalse(Files.exists(newProjectPath));
//create project via nio