Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

CB-6051 ability to download drivers #3155

Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
3626613
CB-6051 wip
yagudin10 Dec 24, 2024
ea11343
CB-6051 refresh drivers after loading server config
yagudin10 Dec 24, 2024
fed0445
Merge remote-tracking branch 'origin/devel' into CB-6051-ability-to-d…
yagudin10 Dec 24, 2024
e297174
CB-6051 api for lib file info
yagudin10 Dec 24, 2024
85baf9c
CB-6071 show installed status
devnaumov Dec 24, 2024
b6c9d9e
Merge branch 'CB-6051-ability-to-download-driver-from-the-maven-repos…
devnaumov Dec 24, 2024
f16a950
Merge branch 'devel' into CB-6051-ability-to-download-driver-from-the…
devnaumov Dec 25, 2024
847838e
Merge remote-tracking branch 'origin/devel' into CB-6051-ability-to-d…
yagudin10 Dec 25, 2024
2d4d151
CB-6051 make icon larger
devnaumov Dec 25, 2024
8f78a09
Merge branch 'CB-6051-ability-to-download-driver-from-the-maven-repos…
devnaumov Dec 25, 2024
690d71d
CB-6051 move out applicable drivers from platform class
yagudin10 Dec 26, 2024
343c5b4
Merge branch 'devel' into CB-6051-ability-to-download-driver-from-the…
EvgeniaBzzz Dec 26, 2024
861a29b
CB-6051 fix detect external dependencies for te
yagudin10 Dec 27, 2024
1cda706
CB-6051 add driver status to the connection form
devnaumov Dec 29, 2024
de61206
Merge branch 'CB-6051-ability-to-download-driver-from-the-maven-repos…
devnaumov Dec 29, 2024
c89b9a7
CB-6051 fix error if driver is not found
yagudin10 Dec 31, 2024
5a2432b
Merge branch 'devel' into CB-6051-ability-to-download-driver-from-the…
yagudin10 Jan 6, 2025
0415053
CB-6051 add comments
yagudin10 Jan 6, 2025
b3c36c9
Merge branch 'devel' into CB-6051-ability-to-download-driver-from-the…
dariamarutkina Jan 8, 2025
3c98139
CB-6051 add param that checks when libs can be downloaded
yagudin10 Jan 9, 2025
5dbc8fb
CB-6051 add downloadable flag
devnaumov Jan 9, 2025
ad8d6a4
Merge branch 'devel' into CB-6051-ability-to-download-driver-from-the…
devnaumov Jan 10, 2025
a7c4a59
CB-6051 check admin permission before showing status
devnaumov Jan 10, 2025
493cd7d
CB-6051 remove uninstalled drivers from list for non-admin users
devnaumov Jan 10, 2025
9e1107b
CB-6051 add logic to options
devnaumov Jan 10, 2025
1757d43
Merge branch 'devel' into CB-6051-ability-to-download-driver-from-the…
dariamarutkina Jan 10, 2025
4b82cb3
CB-6051 do not reset custom driver and fix message
yagudin10 Jan 13, 2025
ddf6b9e
CB-6051 add buttonText prop
devnaumov Jan 13, 2025
7d9629b
Merge branch 'devel' into CB-6051-ability-to-download-driver-from-the…
dariamarutkina Jan 13, 2025
9ec0172
Merge branch 'devel' into CB-6051-ability-to-download-driver-from-the…
dariamarutkina Jan 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,9 @@
return webDrivers.contains(driver.getFullId());
}


public boolean validateDriverFilesAvailability() {

Check warning on line 67 in server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebDriverRegistry.java

View workflow job for this annotation

GitHub Actions / Server / Lint

[checkstyle] reported by reviewdog 🐶 Missing a Javadoc comment. Raw Output: /github/workspace/./server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebDriverRegistry.java:67:5: warning: Missing a Javadoc comment. (com.puppycrawl.tools.checkstyle.checks.javadoc.MissingJavadocMethodCheck)

Check warning on line 67 in server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebDriverRegistry.java

View check run for this annotation

Jenkins-CI-integration / CheckStyle Java Report

server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebDriverRegistry.java#L67

Missing a Javadoc comment.
return true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,7 @@ protected void sendConfigChangedEvent(SMCredentialsProvider credentialsProvider)
public abstract CBServerConfigurationController<T> getServerConfigurationController();

private void refreshDisabledDriversConfig() {
CBPlatform.getInstance().refreshApplicableDrivers();
CBAppConfig config = getAppConfiguration();
Set<String> disabledDrivers = new LinkedHashSet<>(Arrays.asList(config.getDisabledDrivers()));
for (DBPDriver driver : CBPlatform.getInstance().getApplicableDrivers()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package io.cloudbeaver.server;

import io.cloudbeaver.auth.NoAuthCredentialsProvider;
import io.cloudbeaver.registry.WebDriverRegistry;
import io.cloudbeaver.server.jobs.SessionStateJob;
import io.cloudbeaver.server.jobs.WebDataSourceMonitorJob;
import io.cloudbeaver.server.jobs.WebSessionMonitorJob;
Expand All @@ -39,6 +40,7 @@

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -76,8 +78,6 @@
log.info("Initialize web platform...: ");
this.preferenceStore = new WebServerPreferenceStore(WebPlatformActivator.getInstance().getPreferences());
super.initialize();
refreshApplicableDrivers();

scheduleServerJobs();
log.info("Web platform initialized (" + (System.currentTimeMillis() - startTime) + "ms)");
}
Expand Down Expand Up @@ -140,21 +140,22 @@
return false;
}

public void refreshApplicableDrivers() {

Check warning on line 143 in server/bundles/io.cloudbeaver.server.ce/src/io/cloudbeaver/server/CBPlatform.java

View workflow job for this annotation

GitHub Actions / Server / Lint

[checkstyle] reported by reviewdog 🐶 Missing a Javadoc comment. Raw Output: /github/workspace/./server/bundles/io.cloudbeaver.server.ce/src/io/cloudbeaver/server/CBPlatform.java:143:5: warning: Missing a Javadoc comment. (com.puppycrawl.tools.checkstyle.checks.javadoc.MissingJavadocMethodCheck)
this.applicableDrivers.clear();
assert application != null;
WebDriverRegistry driverRegistry = application.getDriverRegistry();

for (DBPDataSourceProviderDescriptor dspd : DataSourceProviderRegistry.getInstance().getEnabledDataSourceProviders()) {
for (DBPDriver driver : dspd.getEnabledDrivers()) {
List<? extends DBPDriverLibrary> libraries = driver.getDriverLibraries();
{
if (!application.getDriverRegistry().isDriverEnabled(driver)) {
if (!driverRegistry.isDriverEnabled(driver)) {
continue;
}
boolean hasAllFiles = true, hasJars = false;

Check warning on line 155 in server/bundles/io.cloudbeaver.server.ce/src/io/cloudbeaver/server/CBPlatform.java

View workflow job for this annotation

GitHub Actions / Server / Lint

[checkstyle] reported by reviewdog 🐶 Each variable declaration must be in its own statement. Raw Output: /github/workspace/./server/bundles/io.cloudbeaver.server.ce/src/io/cloudbeaver/server/CBPlatform.java:155:21: warning: Each variable declaration must be in its own statement. (com.puppycrawl.tools.checkstyle.checks.coding.MultipleVariableDeclarationsCheck)
for (DBPDriverLibrary lib : libraries) {
if (!DBWorkbench.isDistributed() && !lib.isOptional() && lib.getType() != DBPDriverLibrary.FileType.license &&
(lib.getLocalFile() == null || !Files.exists(lib.getLocalFile())))
if (driverRegistry.validateDriverFilesAvailability() && !isDriverLibraryFilePresent(lib))
{

Check warning on line 158 in server/bundles/io.cloudbeaver.server.ce/src/io/cloudbeaver/server/CBPlatform.java

View workflow job for this annotation

GitHub Actions / Server / Lint

[checkstyle] reported by reviewdog 🐶 '{' at column 25 should be on the previous line. Raw Output: /github/workspace/./server/bundles/io.cloudbeaver.server.ce/src/io/cloudbeaver/server/CBPlatform.java:158:25: warning: '{' at column 25 should be on the previous line. (com.puppycrawl.tools.checkstyle.checks.blocks.LeftCurlyCheck)
hasAllFiles = false;
log.error("\tDriver '" + driver.getId() + "' is missing library '" + lib.getDisplayName() + "'");
} else {
Expand All @@ -172,6 +173,14 @@
log.info("Available drivers: " + applicableDrivers.stream().map(DBPDriver::getFullName).collect(Collectors.joining(",")));
}

private boolean isDriverLibraryFilePresent(@NotNull DBPDriverLibrary lib) {
if (lib.getType() == DBPDriverLibrary.FileType.license) {
return true;
}
Path localFile = lib.getLocalFile();
return localFile != null && Files.exists(localFile);
}

@NotNull
@Override
public DBFileController createFileController() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,13 @@ type DriverLibraryInfo {
id: ID!
name: String!
icon: String
libraryFiles: [DriverFileInfo!]
}

type DriverFileInfo @since(version: "24.3.2") {
id: ID!
fileName: String!
icon: String
}

enum ResultDataFormat {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,4 +400,11 @@
}
return webProps.toArray(new WebPropertyInfo[0]);
}

public static void validateDriverLibrariesPresence(@NotNull DBPDataSourceContainer container) throws DBWebException {

Check warning on line 404 in server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/WebServiceUtils.java

View workflow job for this annotation

GitHub Actions / Server / Lint

[checkstyle] reported by reviewdog 🐶 Missing a Javadoc comment. Raw Output: /github/workspace/./server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/WebServiceUtils.java:404:5: warning: Missing a Javadoc comment. (com.puppycrawl.tools.checkstyle.checks.javadoc.MissingJavadocMethodCheck)

Check warning on line 404 in server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/WebServiceUtils.java

View check run for this annotation

Jenkins-CI-integration / CheckStyle Java Report

server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/WebServiceUtils.java#L404

Missing a Javadoc comment.
if (container.getDriver().needsExternalDependencies()) {
throw new DBWebException("Driver files for %s are not found. Please, ask administrator to download it."
.formatted(container.getDriver().getName()));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public class WebDatabaseDriverInfo {
public static final String URL_DATABASE_FIELD = ".*(?:\\{(?:database|file|folder)}).*";
private final WebSession webSession;
private final DBPDriver driver;
private String id;
private final String id;

public WebDatabaseDriverInfo(WebSession webSession, DBPDriver driver) {
this.webSession = webSession;
Expand Down Expand Up @@ -296,13 +296,13 @@ public boolean getRequiresDatabaseName() {
@Property
public WebDriverLibraryInfo[] getDriverLibraries() {
return driver.getDriverLibraries().stream()
.map(dbpDriverLibrary -> new WebDriverLibraryInfo(webSession, dbpDriverLibrary))
.map(dbpDriverLibrary -> new WebDriverLibraryInfo(driver, dbpDriverLibrary))
.toArray(WebDriverLibraryInfo[]::new);
}

@Property
public boolean isDriverInstalled() {
return !driver.needsExternalDependencies(webSession.getProgressMonitor());
return !driver.needsExternalDependencies();
}

@Property
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2024 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;

import io.cloudbeaver.WebServiceUtils;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.model.DBIcon;
import org.jkiss.dbeaver.model.connection.DBPDriverLibrary;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.registry.driver.DriverDescriptor;

public class WebDriverLibraryFileInfo {

@NotNull
private final DriverDescriptor.DriverFileInfo fileInfo;

public WebDriverLibraryFileInfo(@NotNull DriverDescriptor.DriverFileInfo fileInfo) {
this.fileInfo = fileInfo;
}


@Property
public String getId() {
return fileInfo.getId();
}

@Property
public String getFileName() {
return fileInfo.toString();
}

@Property
public String getIcon() {
if (fileInfo.getType() == DBPDriverLibrary.FileType.license) {
return WebServiceUtils.makeIconId(DBIcon.TYPE_TEXT);
}
return WebServiceUtils.makeIconId(DBIcon.JAR);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,24 @@
package io.cloudbeaver.model;

import io.cloudbeaver.WebServiceUtils;
import io.cloudbeaver.model.session.WebSession;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.model.connection.DBPDriver;
import org.jkiss.dbeaver.model.connection.DBPDriverLibrary;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.registry.driver.DriverDescriptor;

import java.util.List;

public class WebDriverLibraryInfo {

private final WebSession webSession;
@NotNull
private final DBPDriver driver;
@NotNull
private final DBPDriverLibrary driverLibrary;

public WebDriverLibraryInfo(@NotNull WebSession webSession, @NotNull DBPDriverLibrary driverLibrary) {
this.webSession = webSession;
public WebDriverLibraryInfo(@NotNull DBPDriver driver, @NotNull DBPDriverLibrary driverLibrary) {
this.driver = driver;
this.driverLibrary = driverLibrary;
}

Expand All @@ -43,6 +49,18 @@ public String getName() {
return driverLibrary.getDisplayName();
}

@Property
@Nullable
public List<WebDriverLibraryFileInfo> getLibraryFiles() {
var libraryFiles = ((DriverDescriptor) driver).getLibraryFiles(driverLibrary);
if (libraryFiles == null) {
return null;
}
return libraryFiles.stream()
.map(WebDriverLibraryFileInfo::new)
.toList();
}

@Property
public String getIcon() {
return WebServiceUtils.makeIconId(driverLibrary.getIcon());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,10 @@ public WebConnectionInfo initConnection(
}

boolean oldSavePassword = dataSourceContainer.isSavePassword();
DBRProgressMonitor monitor = webSession.getProgressMonitor();
WebServiceUtils.validateDriverLibrariesPresence(dataSourceContainer);
try {
boolean connect = dataSourceContainer.connect(webSession.getProgressMonitor(), true, false);
boolean connect = dataSourceContainer.connect(monitor, true, false);
if (connect) {
webSession.addSessionEvent(
new WSDataSourceConnectEvent(
Expand Down Expand Up @@ -755,6 +757,7 @@ public WebConnectionInfo testConnection(
testDataSource = (DataSourceDescriptor) WebServiceUtils.createConnectionFromConfig(connectionConfig,
sessionRegistry);
}
WebServiceUtils.validateDriverLibrariesPresence(testDataSource);
webSession.provideAuthParameters(webSession.getProgressMonitor(),
testDataSource,
testDataSource.getConnectionConfiguration());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ fragment DatabaseDriver on DriverInfo {
applicableAuthModels
applicableNetworkHandlers
configurationTypes
driverId
driverInstalled

mainProperties @include(if: $includeMainProperties) {
...DriverPropertyInfo
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,24 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
.icon {
position: relative;
}

.staticImage {
box-sizing: border-box;
width: 24px;
max-height: 24px;
};
}

.indicator {
position: absolute;
bottom: 2px;
right: 0;
width: 12px;
height: 12px;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

may be we need a bit more larger icon? this one seems too small for me
image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, If we expect users to hover over that icon, it's better to have it at least 14px or 16px. WCAG recommends minimum 24px, however in our case it's not a button and maybe not so critical, so we can make it smaller.
And I personally would place it on top. For users it will make more sense in terms of catching their attention since such approach is commonly used among many applications for different type of notifications.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I have a better Idea. Why don't we just make the whole driver icon hoverable? I assume this is how it should work. Icon itself doesn't need to be a target

display: flex;
border-radius: 50%;
background-color: var(--theme-surface);
border: 1px solid var(--theme-surface);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { observer } from 'mobx-react-lite';
import { useCallback } from 'react';

import { ListItem, ListItemDescription, ListItemIcon, ListItemName, s, StaticImage, useS } from '@cloudbeaver/core-blocks';
import { IconOrImage, ListItem, ListItemDescription, ListItemIcon, ListItemName, s, StaticImage, useS, useTranslate } from '@cloudbeaver/core-blocks';

import style from './Driver.module.css';

Expand All @@ -17,6 +17,7 @@ export interface IDriver {
icon?: string;
name?: string;
description?: string;
driverInstalled?: boolean;
}

interface Props {
Expand All @@ -25,13 +26,19 @@ interface Props {
}

export const Driver = observer<Props>(function Driver({ driver, onSelect }) {
const translate = useTranslate();
const select = useCallback(() => onSelect(driver.id), [driver]);
const styles = useS(style);

return (
<ListItem onClick={select}>
<ListItemIcon>
<ListItemIcon className={s(styles, { icon: true })}>
<StaticImage icon={driver.icon} className={s(styles, { staticImage: true })} />
{!driver.driverInstalled && (
<div className={s(styles, { indicator: true })} title={translate('plugin_connection_custom_drivers_driver_not_installed')}>
<IconOrImage icon="/icons/info_icon.svg" />
</div>
)}
</ListItemIcon>
<ListItemName>{driver.name}</ListItemName>
<ListItemDescription title={driver.description}>{driver.description}</ListItemDescription>
Expand Down
5 changes: 4 additions & 1 deletion webapp/packages/plugin-connection-custom/src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
export default [['plugin_connection_custom_action_custom_label', 'New Connection']];
export default [
['plugin_connection_custom_action_custom_label', 'New Connection'],
['plugin_connection_custom_drivers_driver_not_installed', 'Driver is not installed'],
];
5 changes: 4 additions & 1 deletion webapp/packages/plugin-connection-custom/src/locales/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
export default [['plugin_connection_custom_action_custom_label', 'Nouvelle connexion']];
export default [
['plugin_connection_custom_action_custom_label', 'Nouvelle connexion'],
['plugin_connection_custom_drivers_driver_not_installed', 'Driver is not installed'],
];
5 changes: 4 additions & 1 deletion webapp/packages/plugin-connection-custom/src/locales/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
export default [['plugin_connection_custom_action_custom_label', 'New Connection']];
export default [
['plugin_connection_custom_action_custom_label', 'New Connection'],
['plugin_connection_custom_drivers_driver_not_installed', 'Driver is not installed'],
];
5 changes: 4 additions & 1 deletion webapp/packages/plugin-connection-custom/src/locales/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
export default [['plugin_connection_custom_action_custom_label', 'Новое подключение']];
export default [
['plugin_connection_custom_action_custom_label', 'Новое подключение'],
['plugin_connection_custom_drivers_driver_not_installed', 'Драйвер не установлен'],
];
5 changes: 4 additions & 1 deletion webapp/packages/plugin-connection-custom/src/locales/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
export default [['plugin_connection_custom_action_custom_label', '新建连接']];
export default [
['plugin_connection_custom_action_custom_label', '新建连接'],
['plugin_connection_custom_drivers_driver_not_installed', 'Driver is not installed'],
];
Loading