From bfd15751c769829deddda30b95a71f50d6b01201 Mon Sep 17 00:00:00 2001 From: Aleksandr Skoblikov Date: Mon, 5 Sep 2022 20:01:43 +0300 Subject: [PATCH 01/10] CB-2545 fix web session context --- .../model/session/SMWebSessionContext.java | 65 ------------------- .../cloudbeaver/model/session/WebSession.java | 3 +- 2 files changed, 1 insertion(+), 67 deletions(-) delete mode 100644 server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/SMWebSessionContext.java diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/SMWebSessionContext.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/SMWebSessionContext.java deleted file mode 100644 index 2db79cbe59..0000000000 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/SMWebSessionContext.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * DBeaver - Universal Database Manager - * Copyright (C) 2010-2022 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.session; - -import org.jkiss.code.NotNull; -import org.jkiss.code.Nullable; -import org.jkiss.dbeaver.DBException; -import org.jkiss.dbeaver.model.auth.SMAuthSpace; -import org.jkiss.dbeaver.model.auth.SMAuthToken; -import org.jkiss.dbeaver.model.auth.SMSession; -import org.jkiss.dbeaver.model.auth.SMSessionContext; -import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; - -public class SMWebSessionContext implements SMSessionContext { - - private final WebSession session; - private final SMSessionContext parentContext; - - public SMWebSessionContext(SMSessionContext parentContext, WebSession session) { - this.parentContext = parentContext; - this.session = session; - } - - @Nullable - @Override - public SMSession getSpaceSession(@NotNull DBRProgressMonitor monitor, @NotNull SMAuthSpace space, boolean open) throws DBException { - return parentContext.getSpaceSession(monitor, session.getSessionSpace(), open); - } - - @Nullable - @Override - public SMSession findSpaceSession(@NotNull SMAuthSpace space) { - return parentContext.findSpaceSession(session.getSessionSpace()); - } - - @Override - public SMAuthToken[] getSavedTokens() { - return parentContext.getSavedTokens(); - } - - @Override - public void addSession(@NotNull SMSession session) { - parentContext.addSession(session); - } - - @Override - public boolean removeSession(@NotNull SMSession session) { - return parentContext.removeSession(session); - } -} 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 8a3fcb092b..576bec1450 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 @@ -352,10 +352,9 @@ public class WebSession extends AbstractSessionPersistent implements SMSession, public VirtualProjectImpl createVirtualProject(RMProject project) { // Do not filter data sources from user project DataSourceFilter filter = project.getType() == RMProject.Type.USER ? x -> true : this::isDataSourceAccessible; - SMSessionContext projectSessionContext = new SMWebSessionContext(sessionAuthContext, this); VirtualProjectImpl sessionProject = application.createProjectImpl( project, - projectSessionContext, + sessionAuthContext, this, filter); DBPDataSourceRegistry dataSourceRegistry = sessionProject.getDataSourceRegistry(); From ac4841e815336753701390eef808031b78fa4d55 Mon Sep 17 00:00:00 2001 From: serge-rider Date: Wed, 7 Sep 2022 09:37:17 +0200 Subject: [PATCH 02/10] dbeaver/dbeaver-ee#1905 Driver controller model, use config controllers to load/save drivers --- .../io/cloudbeaver/server/WebPlatformActivator.java | 10 ---------- .../src/io/cloudbeaver/server/CBPlatform.java | 6 +++--- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/server/WebPlatformActivator.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/server/WebPlatformActivator.java index d883272519..e3c97cb7cf 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/server/WebPlatformActivator.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/server/WebPlatformActivator.java @@ -72,16 +72,6 @@ public class WebPlatformActivator extends Plugin { super.stop(context); } - /** - * Returns configuration file - */ - public static synchronized File getConfigurationFile(String fileName) { - if (configDir == null) { - configDir = getInstance().getStateLocation().toFile(); - } - return new File(configDir, fileName); - } - public DBPPreferenceStore getPreferences() { return preferences; } diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatform.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatform.java index da00499683..e64aed6c67 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatform.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatform.java @@ -21,6 +21,7 @@ import io.cloudbeaver.registry.WebDriverRegistry; import io.cloudbeaver.service.session.WebSessionManager; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Plugin; import org.jkiss.code.NotNull; import org.jkiss.code.Nullable; import org.jkiss.dbeaver.DBException; @@ -268,10 +269,9 @@ public class CBPlatform extends BasePlatformImpl { return folder.toFile(); } - @NotNull @Override - public File getConfigurationFile(String fileName) { - return WebPlatformActivator.getConfigurationFile(fileName); + protected Plugin getProductPlugin() { + return WebPlatformActivator.getInstance(); } @Override From 47961b283b9ce15579122d12dc209d5d0c5f775f Mon Sep 17 00:00:00 2001 From: kseniaguzeeva <112612526+kseniaguzeeva@users.noreply.github.com> Date: Wed, 7 Sep 2022 11:03:51 +0300 Subject: [PATCH 03/10] CB-123 chore: update README --- README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/README.md b/README.md index 44fdfae0f3..e90490e3f1 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,34 @@ You can see live demo of CloudBeaver here: https://demo.cloudbeaver.io ## Changelog +### CloudBeaver 22.2.0 - 2022-09-06 + +Changes since 22.1.0 +- Public page: + - administrators can create shared connections via the Connection menu. +- Resource Manager: + - users can group scripts into folders; + - when internet connection is lost, script editing is disabled to prevent users from losing data; + - users can refresh all scripts by clicking one button; + - users can rename scripts. +- Database Navigator: + - users can group connections into folders. +- SQL Editor: + - "Link with Editor" tool is now available for the SQL Editor and synchronizes it with the element in the Database Navigator; + - script formatting can be undone. +- The Data Editor: + - non-editable tables are marked; + - users can change the coordinate system for spatial data in the Value panel. +- Local configuration: + - the application language can be set; + - the number of table rows to load can be configured to prevent the application from slowing down in the following cases: + - the default number of loaded rows when users open a table and then scroll it, + - the minimum and maximum number of rows, which users can load at once when scrolling the table; + - SQL query execution time limit can be changed; +- The cookies can be disabled. +- The product upgrade scripts were improved to avoid possible UI issues. +- A lot of small bug fixes, enhancements and improvements have been made. + ### CloudBeaver 22.1.4 - 2022-08-08 - Local configuration: - The structure of the local configuration file has been improved to simplify the modification process; From ba3e26453b0a6afb753b27312ff40c995130e800 Mon Sep 17 00:00:00 2001 From: serge-rider Date: Wed, 7 Sep 2022 11:27:40 +0200 Subject: [PATCH 04/10] dbeaver/dbeaver-ee#1905 Switch local configs to NIO --- .../rm/local/LocalResourceController.java | 6 +-- .../src/io/cloudbeaver/server/CBPlatform.java | 4 +- .../service/sql/WebSQLDataLOBReceiver.java | 16 +++++--- .../service/sql/WebSQLResultServlet.java | 15 ++++--- .../cloudbeaver/service/sql/WebSQLUtils.java | 4 +- .../transfer/impl/WebDataTransferServlet.java | 10 ++--- .../impl/WebDataTransferTaskConfig.java | 18 ++++---- .../transfer/impl/WebServiceDataTransfer.java | 41 ++++++++++--------- 8 files changed, 62 insertions(+), 52 deletions(-) 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 7f5f39f361..c11891bbf7 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 @@ -204,7 +204,7 @@ public class LocalResourceController implements RMController { public RMProject createProject(@NotNull String name, @Nullable String description) throws DBException { if (!Files.exists(sharedProjectsPath)) { try { - Files.createDirectory(sharedProjectsPath); + Files.createDirectories(sharedProjectsPath); } catch (IOException e) { throw new DBException("Error creating shared project path", e); } @@ -216,7 +216,7 @@ public class LocalResourceController implements RMController { throw new DBException("Project '" + name + "' already exists"); } try { - Files.createDirectory(getProjectPath(project.getId())); + Files.createDirectories(getProjectPath(project.getId())); return project; } catch (IOException e) { throw new DBException("Error creating project path", e); @@ -354,7 +354,7 @@ public class LocalResourceController implements RMController { } try { if (isFolder) { - Files.createDirectory(targetPath); + Files.createDirectories(targetPath); } else { Files.createFile(targetPath); } diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatform.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatform.java index e64aed6c67..598dbdb69b 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatform.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatform.java @@ -245,7 +245,7 @@ public class CBPlatform extends BasePlatformImpl { } @NotNull - public File getTempFolder(DBRProgressMonitor monitor, String name) { + public Path getTempFolder(DBRProgressMonitor monitor, String name) { if (tempFolder == null) { // Make temp folder monitor.subTask("Create temp folder"); @@ -266,7 +266,7 @@ public class CBPlatform extends BasePlatformImpl { log.error("Error creating temp folder '" + folder.toAbsolutePath() + "'", e); } } - return folder.toFile(); + return folder; } @Override diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLDataLOBReceiver.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLDataLOBReceiver.java index a5d5a34309..635e857d8e 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLDataLOBReceiver.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLDataLOBReceiver.java @@ -28,9 +28,9 @@ import org.jkiss.dbeaver.model.struct.DBSDataContainer; import org.jkiss.dbeaver.utils.ContentUtils; import org.jkiss.utils.CommonUtils; -import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.Path; import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.util.List; @@ -38,7 +38,7 @@ import java.util.List; public class WebSQLDataLOBReceiver implements DBDDataReceiver { private static final Log log = Log.getLog(WebSQLDataLOBReceiver.class); - public static final File DATA_EXPORT_FOLDER = CBPlatform.getInstance().getTempFolder(new VoidProgressMonitor(), "sql-lob-files"); + public static final Path DATA_EXPORT_FOLDER = CBPlatform.getInstance().getTempFolder(new VoidProgressMonitor(), "sql-lob-files"); private final String tableName; private final DBSDataContainer dataContainer; @@ -51,8 +51,12 @@ public class WebSQLDataLOBReceiver implements DBDDataReceiver { this.tableName = tableName; this.dataContainer = dataContainer; this.rowIndex = rowIndex; - if (!DATA_EXPORT_FOLDER.exists()){ - DATA_EXPORT_FOLDER.mkdirs(); + if (!Files.exists(DATA_EXPORT_FOLDER)){ + try { + Files.createDirectories(DATA_EXPORT_FOLDER); + } catch (IOException e) { + log.error("Error creating temp folder", e); + } } } @@ -81,8 +85,8 @@ public class WebSQLDataLOBReceiver implements DBDDataReceiver { throw new DBQuotaException( "Data export quota exceeded", CBConstants.QUOTA_PROP_FILE_LIMIT, fileSizeLimit.longValue(), binaryValue.length); } - File file = new File(DATA_EXPORT_FOLDER, exportFileName); - Files.write(file.toPath(), binaryValue); + Path file = DATA_EXPORT_FOLDER.resolve(exportFileName); + Files.write(file, binaryValue); return exportFileName; } diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLResultServlet.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLResultServlet.java index b711238394..bd55958c2e 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLResultServlet.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLResultServlet.java @@ -17,11 +17,10 @@ import javax.servlet.annotation.MultipartConfig; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; +import java.nio.file.Path; import java.util.UUID; import java.util.regex.Pattern; @@ -29,7 +28,7 @@ import java.util.regex.Pattern; public class WebSQLResultServlet extends WebServiceServletBase { private static final Log log = Log.getLog(WebSQLResultServlet.class); - private static final MultipartConfigElement MULTI_PART_CONFIG = new MultipartConfigElement(WebSQLDataLOBReceiver.DATA_EXPORT_FOLDER.getAbsolutePath()); + private static final MultipartConfigElement MULTI_PART_CONFIG = new MultipartConfigElement(WebSQLDataLOBReceiver.DATA_EXPORT_FOLDER.toAbsolutePath().toString()); // context-id/result-id/row-number/attribute-name private static final Pattern URL_PATTERN = Pattern.compile("/?([\\w]+)/([0-9]+)/([0-9]+)/([0-9]+)/(.+)[/\\?]?"); @@ -68,18 +67,18 @@ public class WebSQLResultServlet extends WebServiceServletBase { valuePath = valuePath.substring(1); } - File dataFile = new File(WebSQLDataLOBReceiver.DATA_EXPORT_FOLDER, valuePath); + Path dataFile = WebSQLDataLOBReceiver.DATA_EXPORT_FOLDER.resolve(valuePath); session.addInfoMessage("Download LOB file ..."); response.setHeader("Content-Type", "application/octet-stream"); - response.setHeader("Content-Disposition", "attachment; filename=\"" + dataFile.getName() + "\""); - response.setHeader("Content-Length", String.valueOf(dataFile.length())); + response.setHeader("Content-Disposition", "attachment; filename=\"" + dataFile.getFileName().toString() + "\""); + response.setHeader("Content-Length", String.valueOf(Files.size(dataFile))); response.setDateHeader("Expires", System.currentTimeMillis() + CBStaticServlet.STATIC_CACHE_SECONDS * 1000); response.setHeader("Cache-Control", "public, max-age=" + CBStaticServlet.STATIC_CACHE_SECONDS); - try (InputStream is = new FileInputStream(dataFile)) { + try (InputStream is = Files.newInputStream(dataFile)) { IOUtils.copyStream(is, response.getOutputStream()); } - Files.deleteIfExists(dataFile.toPath()); + Files.deleteIfExists(dataFile); } } } \ No newline at end of file diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLUtils.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLUtils.java index 74ca228f4b..a464549408 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLUtils.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLUtils.java @@ -39,9 +39,9 @@ import org.jkiss.utils.Base64; import org.jkiss.utils.CommonUtils; import java.io.ByteArrayOutputStream; -import java.io.File; import java.math.BigDecimal; import java.nio.charset.StandardCharsets; +import java.nio.file.Path; import java.util.*; /** @@ -211,7 +211,7 @@ public class WebSQLUtils { case WebSQLConstants.VALUE_TYPE_CONTENT: { if (map.get(WebSQLConstants.ATTR_BINARY) != null) { DBDContentStorage storage; - File openFile = new File(WebSQLDataLOBReceiver.DATA_EXPORT_FOLDER, (String) map.get("fileName")); + Path openFile = WebSQLDataLOBReceiver.DATA_EXPORT_FOLDER.resolve((String) map.get("fileName")); Object tempValue = ((DBDAttributeBinding) attribute).getValueHandler().getValueFromObject( session, attribute, diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferServlet.java b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferServlet.java index 3ab5a9471f..623be196df 100644 --- a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferServlet.java +++ b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferServlet.java @@ -14,10 +14,10 @@ import org.jkiss.utils.IOUtils; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; public class WebDataTransferServlet extends WebServiceServletBase { @@ -56,13 +56,13 @@ public class WebDataTransferServlet extends WebServiceServletBase { fileName = taskInfo.getDataFileId(); } - File dataFile = taskInfo.getDataFile(); + Path dataFile = taskInfo.getDataFile(); session.addInfoMessage("Download data ..."); response.setHeader("Content-Type", processor.getContentType()); response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); - response.setHeader("Content-Length", String.valueOf(dataFile.length())); + response.setHeader("Content-Length", String.valueOf(Files.size(dataFile))); - try (InputStream is = new FileInputStream(dataFile)) { + try (InputStream is = Files.newInputStream(dataFile)) { IOUtils.copyStream(is, response.getOutputStream()); } diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferTaskConfig.java b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferTaskConfig.java index f9ebb9aa80..c56f0c73c2 100644 --- a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferTaskConfig.java +++ b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferTaskConfig.java @@ -2,27 +2,29 @@ package io.cloudbeaver.service.data.transfer.impl; import org.jkiss.dbeaver.Log; -import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; public class WebDataTransferTaskConfig { private static final Log log = Log.getLog(WebDataTransferTaskConfig.class); - private File dataFile; + private Path dataFile; private WebDataTransferParameters parameters; private String exportFileName; - public WebDataTransferTaskConfig(File dataFile, WebDataTransferParameters parameters) { + public WebDataTransferTaskConfig(Path dataFile, WebDataTransferParameters parameters) { this.dataFile = dataFile; this.parameters = parameters; } - public File getDataFile() { + public Path getDataFile() { return dataFile; } public String getDataFileId() { - return dataFile.getName(); + return dataFile.getFileName().toString(); } public WebDataTransferParameters getParameters() { @@ -38,8 +40,10 @@ public class WebDataTransferTaskConfig { } public void deleteFile() { - if (!dataFile.delete()) { - log.error("Error deleting export file " + dataFile.getAbsolutePath()); + try { + Files.delete(dataFile); + } catch (IOException e) { + log.error("Error deleting export file " + dataFile.toAbsolutePath(), e); } } } \ No newline at end of file diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebServiceDataTransfer.java b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebServiceDataTransfer.java index 7f3860c785..81fc63357f 100644 --- a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebServiceDataTransfer.java +++ b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebServiceDataTransfer.java @@ -51,9 +51,10 @@ import org.jkiss.dbeaver.tools.transfer.stream.StreamTransferConsumer; import org.jkiss.dbeaver.utils.ContentUtils; import org.jkiss.utils.CommonUtils; -import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.*; import java.util.stream.Collectors; @@ -66,21 +67,19 @@ public class WebServiceDataTransfer implements DBWServiceDataTransfer { private static final Log log = Log.getLog(WebServiceDataTransfer.class); - private final File dataExportFolder; + private final Path dataExportFolder; public WebServiceDataTransfer() { dataExportFolder = CBPlatform.getInstance().getTempFolder(new VoidProgressMonitor(), "data-transfer"); ContentUtils.deleteFileRecursive(dataExportFolder); - if (!dataExportFolder.mkdirs()) { - log.error("Error re-creating temporary folder"); + try { + Files.createDirectories(dataExportFolder); + } catch (IOException e) { + log.error("Error re-creating temporary folder", e); } } - public File getDataExportFolder() { - return dataExportFolder; - } - @Override public List getAvailableStreamProcessors(WebSession session) { List processors = DataTransferRegistry.getInstance().getAvailableProcessors(StreamTransferConsumer.class, DBSEntity.class); @@ -130,10 +129,12 @@ public class WebServiceDataTransfer implements DBWServiceDataTransfer { if (taskInfo == null) { throw new DBWebException("Session task '" + dataFileId + "' not found"); } - File dataFile = taskInfo.getDataFile(); + Path dataFile = taskInfo.getDataFile(); if (dataFile != null) { - if (!dataFile.delete()) { - log.warn("Error deleting data file '" + dataFile.getAbsolutePath() + "'"); + try { + Files.delete(dataFile); + } catch (IOException e) { + log.warn("Error deleting data file '" + dataFile.toAbsolutePath() + "'", e); } } dtConfig.removeTask(taskInfo); @@ -151,13 +152,15 @@ public class WebServiceDataTransfer implements DBWServiceDataTransfer { monitor.beginTask("Export data", 1); try { monitor.subTask("Export data using " + processor.getName()); - File exportFile = new File(dataExportFolder, makeUniqueFileName(sqlProcessor, processor)); + Path exportFile = dataExportFolder.resolve(makeUniqueFileName(sqlProcessor, processor)); try { exportData(monitor, processor, dataContainer, parameters, resultsInfo, exportFile); } catch (Exception e) { - if (exportFile.exists()) { - if (!exportFile.delete()) { - log.error("Error deleting export file " + exportFile.getAbsolutePath()); + if (Files.exists(exportFile)) { + try { + Files.delete(exportFile); + } catch (IOException ex) { + log.error("Error deleting export file " + exportFile.toAbsolutePath(), e); } } if (e instanceof DBException) { @@ -170,7 +173,7 @@ public class WebServiceDataTransfer implements DBWServiceDataTransfer { taskConfig.setExportFileName(exportFileName); WebDataTransferUtils.getSessionDataTransferConfig(sqlProcessor.getWebSession()).addTask(taskConfig); - result = exportFile.getName(); + result = exportFile.getFileName().toString(); } catch (Throwable e) { throw new InvocationTargetException(e); } finally { @@ -187,7 +190,7 @@ public class WebServiceDataTransfer implements DBWServiceDataTransfer { DBSDataContainer dataContainer, WebDataTransferParameters parameters, WebSQLResultsInfo resultsInfo, - File exportFile) throws DBException, IOException + Path exportFile) throws DBException, IOException { IDataTransferProcessor processorInstance = processor.getInstance(); if (!(processorInstance instanceof IStreamDataExporter)) { @@ -211,8 +214,8 @@ public class WebServiceDataTransfer implements DBWServiceDataTransfer { StreamConsumerSettings settings = new StreamConsumerSettings(); settings.setOutputEncodingBOM(false); - settings.setOutputFolder(exportFile.getParentFile().getAbsolutePath()); - settings.setOutputFilePattern(exportFile.getName()); + settings.setOutputFolder(exportFile.getParent().toAbsolutePath().toString()); + settings.setOutputFilePattern(exportFile.getFileName().toString()); Map properties = new HashMap<>(); From a2d77271552990cd337281a5bd46dc5231d663a5 Mon Sep 17 00:00:00 2001 From: Konstantin Vasilev Date: Tue, 6 Sep 2022 10:40:44 +0300 Subject: [PATCH 05/10] CB-2514 fix(plugin-connections): Do not show unsaved changes dialog --- .../src/ConnectionForm/Options/ConnectionOptionsTabService.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/Options/ConnectionOptionsTabService.ts b/webapp/packages/plugin-connections/src/ConnectionForm/Options/ConnectionOptionsTabService.ts index 54528cbd67..acc6f743e9 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/Options/ConnectionOptionsTabService.ts +++ b/webapp/packages/plugin-connections/src/ConnectionForm/Options/ConnectionOptionsTabService.ts @@ -237,9 +237,7 @@ export class ConnectionOptionsTabService extends Bootstrap { tempConfig.description = state.config.description; - if (state.projectId === PROJECT_GLOBAL_ID) { - tempConfig.template = state.config.template; - } + tempConfig.template = state.projectId === PROJECT_GLOBAL_ID ? state.config.template : false; tempConfig.driverId = state.config.driverId; From a0bdb375c8037cb22c7eab17b0240130380eea35 Mon Sep 17 00:00:00 2001 From: serge-rider Date: Wed, 7 Sep 2022 16:30:14 +0200 Subject: [PATCH 06/10] dbeaver/dbeaver-ee#1905 Remote config controller --- .../src/io/cloudbeaver/DBWConstants.java | 3 ++- .../src/io/cloudbeaver/model/app/WebApplication.java | 5 +++-- .../src/io/cloudbeaver/server/CBApplication.java | 5 +++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/DBWConstants.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/DBWConstants.java index 747f03b3db..9dfeda52b3 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/DBWConstants.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/DBWConstants.java @@ -22,9 +22,10 @@ package io.cloudbeaver; public class DBWConstants { public static final String PERMISSION_PUBLIC = "public"; - public static final String PERMISSION_ADMIN = "admin"; + public static final String PERMISSION_CONFIGURATION_MANAGER = "configuration-manager"; + public static final String PERMISSION_EDIT_STRUCTURE = "edit-meta"; public static final String PERMISSION_EDIT_DATA = "edit-data"; diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/WebApplication.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/WebApplication.java index 7788a34a03..43a6ba8e53 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/WebApplication.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/WebApplication.java @@ -17,7 +17,7 @@ package io.cloudbeaver.model.app; import io.cloudbeaver.DataSourceFilter; -import io.cloudbeaver.model.session.WebSession; +import io.cloudbeaver.VirtualProjectImpl; import org.jkiss.code.NotNull; import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.model.app.DBPApplication; @@ -27,7 +27,6 @@ import org.jkiss.dbeaver.model.rm.RMController; import org.jkiss.dbeaver.model.rm.RMProject; import org.jkiss.dbeaver.model.security.SMAdminController; import org.jkiss.dbeaver.model.security.SMController; -import io.cloudbeaver.VirtualProjectImpl; import java.nio.file.Path; @@ -41,6 +40,8 @@ public interface WebApplication extends DBPApplication { Path getDataDirectory(boolean create); + Path getWorkspaceDirectory(); + Path getHomeDirectory(); boolean isMultiNode(); diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java index 63e88d14a1..6b3c84d8c6 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java @@ -456,6 +456,11 @@ public class CBApplication extends BaseWebApplication implements WebAuthApplicat return dataDir.toPath(); } + @Override + public Path getWorkspaceDirectory() { + return Path.of(workspaceLocation); + } + private void initializeSecurityController() throws DBException { securityController = createGlobalSecurityController(); } From 4544064ea867f11ec06897f6f35aa2997d555d88 Mon Sep 17 00:00:00 2001 From: Aleksandr Skoblikov Date: Wed, 7 Sep 2022 21:17:35 +0300 Subject: [PATCH 07/10] CB-2559 not update navigator model if context not changed --- .../src/io/cloudbeaver/model/session/WebSession.java | 6 ++++-- .../src/io/cloudbeaver/model/session/WebUserContext.java | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) 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 576bec1450..be9d1f1715 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 @@ -957,8 +957,10 @@ public class WebSession extends AbstractSessionPersistent implements SMSession, } public synchronized void updateSMAuthInfo(SMAuthInfo smAuthInfo) throws DBException { - userContext.refresh(smAuthInfo); - refreshUserData(); + boolean contextChanged = userContext.refresh(smAuthInfo); + if (contextChanged) { + refreshUserData(); + } } @Override 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 fa51e53d89..b47fdccf0c 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 @@ -65,7 +65,7 @@ public class WebUserContext implements SMCredentialsProvider { * @param smAuthInfo - auth info from security manager * @throws DBException - if user already authorized and new token come from another user */ - public synchronized void refresh(SMAuthInfo smAuthInfo) throws DBException { + public synchronized boolean refresh(SMAuthInfo smAuthInfo) throws DBException { if (smAuthInfo.getAuthStatus() != SMAuthStatus.SUCCESS) { throw new DBCException("Authorization did not complete successfully"); } @@ -92,7 +92,7 @@ public class WebUserContext implements SMCredentialsProvider { this.smSessionId = smAuthInfo.getAuthPermissions().getSessionId(); setUser(authPermissions.getUserId() == null ? null : new WebUser(securityController.getUserById(authPermissions.getUserId()))); } - + return isSessionChanged; } public synchronized void refreshSMSession() throws DBException { From a43df1fb705e0474816436ee5d9132d95892e805 Mon Sep 17 00:00:00 2001 From: Wroud Date: Tue, 6 Sep 2022 09:27:27 +0300 Subject: [PATCH 08/10] fix(core-blocks): CB-2500 loader cancellation --- webapp/packages/core-blocks/src/Loader/Loader.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/webapp/packages/core-blocks/src/Loader/Loader.tsx b/webapp/packages/core-blocks/src/Loader/Loader.tsx index f73593f2c6..d6c05ba971 100644 --- a/webapp/packages/core-blocks/src/Loader/Loader.tsx +++ b/webapp/packages/core-blocks/src/Loader/Loader.tsx @@ -116,8 +116,9 @@ export const Loader = observer(function Loader({ if (loading) { if (element.cancel) { + const cancelCopy = onCancel; onCancel = () => { - onCancel?.(); + cancelCopy?.(); element.cancel?.(); }; } From 5ee209f5f11d7849ea914b80bb8b34a4ea9e043c Mon Sep 17 00:00:00 2001 From: Konstantin Vasilev Date: Wed, 7 Sep 2022 16:54:56 +0300 Subject: [PATCH 09/10] CB-2558 fix(plugin-log-viewer): Start logs polling on mount --- .../plugin-log-viewer/src/LogViewer/LogViewerService.ts | 9 ++++----- .../plugin-log-viewer/src/LogViewer/useLogViewer.tsx | 8 ++++++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/webapp/packages/plugin-log-viewer/src/LogViewer/LogViewerService.ts b/webapp/packages/plugin-log-viewer/src/LogViewer/LogViewerService.ts index deb3a26085..cdbdb90acb 100644 --- a/webapp/packages/plugin-log-viewer/src/LogViewer/LogViewerService.ts +++ b/webapp/packages/plugin-log-viewer/src/LogViewer/LogViewerService.ts @@ -63,9 +63,9 @@ export class LogViewerService { toggle(): void { if (this.isActive) { - this.stopLog(); + this.settings.active = false; } else { - this.startLog(); + this.settings.active = true; } } @@ -74,14 +74,14 @@ export class LogViewerService { } async startLog(): Promise { - if (this.isActive) { + if (this.timeoutTaskId !== null) { return; } + if (!this.isLogViewerAvailable()) { throw new Error('Access denied'); } this.failedRequestsCount = 0; - this.settings.active = true; const refreshInterval = this.logViewerSettingsService.settings.isValueDefault('refreshTimeout') ? this.coreSettingsService.settings.getValue('app.logViewer.refreshTimeout') @@ -100,7 +100,6 @@ export class LogViewerService { clearTimeout(this.timeoutTaskId); this.timeoutTaskId = null; } - this.settings.active = false; } clearLog(): void { diff --git a/webapp/packages/plugin-log-viewer/src/LogViewer/useLogViewer.tsx b/webapp/packages/plugin-log-viewer/src/LogViewer/useLogViewer.tsx index 2e86c3d618..752651fb08 100644 --- a/webapp/packages/plugin-log-viewer/src/LogViewer/useLogViewer.tsx +++ b/webapp/packages/plugin-log-viewer/src/LogViewer/useLogViewer.tsx @@ -7,6 +7,7 @@ */ import { observable } from 'mobx'; +import { useEffect } from 'react'; import { useObjectRef, useObservableRef } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; @@ -22,6 +23,13 @@ interface Props { export function useLogViewer() { const logViewerService = useService(LogViewerService); + useEffect(() => { + logViewerService.startLog(); + return () => { + logViewerService.stopLog(); + }; + }, []); + const props: Props = useObservableRef( () => ({ selectedItem: null }), { selectedItem: observable.ref }, From 035e636145962e1197e39296ac2883320f7a5935 Mon Sep 17 00:00:00 2001 From: Wroud Date: Thu, 8 Sep 2022 10:05:40 +0300 Subject: [PATCH 10/10] fix(core-events): CB-2565 autoClose prop for notifications --- webapp/packages/core-events/src/INotification.ts | 2 ++ webapp/packages/core-events/src/NotificationService.ts | 1 + .../src/NotificationsItem/NotificationItemController.ts | 8 ++++++-- .../src/PluginBootstrap.ts | 2 +- .../packages/plugin-sql-editor/src/SqlEditor/useTools.tsx | 1 + 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/webapp/packages/core-events/src/INotification.ts b/webapp/packages/core-events/src/INotification.ts index b25bf6ac7f..12d4e8b5ce 100644 --- a/webapp/packages/core-events/src/INotification.ts +++ b/webapp/packages/core-events/src/INotification.ts @@ -54,6 +54,7 @@ export interface INotification = INo message?: string; timestamp: number; details?: string | Error | null; + autoClose?: boolean; persistent?: boolean; state: { deleteDelay: number }; isSilent: boolean; @@ -69,6 +70,7 @@ export interface INotificationOptions; - constructor(private commonDialogService: CommonDialogService) { + constructor(private readonly commonDialogService: CommonDialogService) { makeObservable(this, { isDetailsDialogOpen: observable, }); @@ -35,7 +35,11 @@ export class NotificationItemController implements IInitializableController { this.handleShowDetails = this.showDetails.bind(this); } - if (notification.type !== ENotificationType.Error && !notification.persistent) { + if ( + notification.type !== ENotificationType.Error + && !notification.persistent + && notification.autoClose !== false + ) { this.closeAfter = FadeTimeout; } } diff --git a/webapp/packages/plugin-sql-editor-navigation-tab-resource/src/PluginBootstrap.ts b/webapp/packages/plugin-sql-editor-navigation-tab-resource/src/PluginBootstrap.ts index ad452d3422..faa055529a 100644 --- a/webapp/packages/plugin-sql-editor-navigation-tab-resource/src/PluginBootstrap.ts +++ b/webapp/packages/plugin-sql-editor-navigation-tab-resource/src/PluginBootstrap.ts @@ -204,7 +204,7 @@ export class PluginBootstrap extends Bootstrap { this.notificationService.logInfo({ title: 'sql_editor_upload_script_max_size_title', message: `Max size: ${maxSize}KB\nFile size: ${size}KB`, - persistent: true, + autoClose: false, }); return; diff --git a/webapp/packages/plugin-sql-editor/src/SqlEditor/useTools.tsx b/webapp/packages/plugin-sql-editor/src/SqlEditor/useTools.tsx index 9640f2b9a4..0c4b6f8c61 100644 --- a/webapp/packages/plugin-sql-editor/src/SqlEditor/useTools.tsx +++ b/webapp/packages/plugin-sql-editor/src/SqlEditor/useTools.tsx @@ -82,6 +82,7 @@ export function useTools(state: ISqlEditorTabState): Readonly { this.notificationService.logInfo({ title: 'sql_editor_upload_script_max_size_title', message: `Max size: ${maxSize}KB\nFile size: ${size}KB`, + autoClose: false, }); return false;