Compare commits

...
Author SHA1 Message Date
Sychev Andrey 932eaf8315 Merge branch 'devel' into dbeaver/pro#7844-cb-lsp-server 2026-03-19 10:14:57 +01:00
Dmitrii Barnukov d0a5c1304a dbeaver/pro#7844 switch lsp ws impl 2026-03-12 15:56:02 +01:00
Dmitrii Barnukov 85d3d834d0 Merge branch 'devel' of github.com:dbeaver/cloudbeaver into dbeaver/pro#7844-cb-lsp-server 2026-03-12 10:20:03 +01:00
Dmitrii Barnukov 09dece1cec Merge branch 'devel' of github.com:dbeaver/cloudbeaver into dbeaver/pro#7844-cb-lsp-server 2026-03-11 15:31:46 +01:00
Dmitrii Barnukov 48057948c2 dbeaver/pro#7844 changed message handler impl 2026-03-11 09:50:29 +01:00
Dmitrii Barnukov ce7107285d Merge branch 'devel' of github.com:dbeaver/cloudbeaver into dbeaver/pro#7844-cb-lsp-server 2026-03-11 09:26:11 +01:00
Dmitrii Barnukov a43355425f Merge branch 'devel' into dbeaver/pro#7844-cb-lsp-server 2026-03-10 17:19:10 +01:00
Sychev Andrey 1aea7c19b6 Merge branch 'devel' into dbeaver/pro#7844-cb-lsp-server 2026-02-19 11:45:07 +01:00
Dmitrii Barnukov 4d0f1a1a43 dbeaver/pro#7844 added missing export 2026-02-19 11:18:15 +01:00
Sychev Andrey de0958add0 Merge branch 'devel' into dbeaver/pro#7844-cb-lsp-server 2026-02-18 10:23:39 +01:00
Dmitrii Barnukov e7ac881fab dbeaver/pro#7844 added copy 2026-02-16 09:40:28 +01:00
Dmitrii Barnukov ec9b9de142 dbeaver/pro#7844 refactor deps, added socket endpoint 2026-02-16 09:39:14 +01:00
Dmitrii Barnukov 974f003a23 Merge branch 'devel' of github.com:dbeaver/cloudbeaver into dbeaver/pro#7844-cb-lsp-server 2026-02-13 14:54:13 +01:00
Dmitrii Barnukov c96e383018 dbeaver/pro#7844 added lsp web socket 2026-02-12 17:43:54 +01:00
6 changed files with 163 additions and 8 deletions
@@ -29,6 +29,8 @@ import io.cloudbeaver.server.servlets.WebStatusServlet;
import io.cloudbeaver.server.websockets.CBEventsLongPollingServlet;
import io.cloudbeaver.server.websockets.CBEventsWebSocket;
import io.cloudbeaver.server.websockets.CBWebSocketServerConfigurator;
import io.cloudbeaver.server.websockets.lsp.LSPWebSocketConstants;
import io.cloudbeaver.server.websockets.lsp.LSPWebSocketEndpoint;
import io.cloudbeaver.service.DBWServiceBindingServlet;
import io.cloudbeaver.service.DBWServiceBindingWebSocket;
import jakarta.websocket.server.ServerEndpointConfig;
@@ -174,13 +176,24 @@ public class CBJettyServer {
JakartaWebSocketServletContainerInitializer.configure(servletContextHandler, (context, container) -> {
// Add echo endpoint to server container
ServerEndpointConfig eventWsEnpoint = ServerEndpointConfig.Builder
CBWebSocketServerConfigurator configurator =
new CBWebSocketServerConfigurator(application.getSessionManager());
ServerEndpointConfig eventWsEndpoint = ServerEndpointConfig.Builder
.create(
CBEventsWebSocket.class,
serverConfiguration.getServicesURI() + "ws"
).configurator(new CBWebSocketServerConfigurator(application.getSessionManager()))
).configurator(configurator)
.build();
container.addEndpoint(eventWsEnpoint);
container.addEndpoint(eventWsEndpoint);
ServerEndpointConfig lspWsEndpoint = ServerEndpointConfig.Builder
.create(
LSPWebSocketEndpoint.class,
serverConfiguration.getServicesURI() + LSPWebSocketConstants.ENDPOINT_SUFFIX
).configurator(configurator)
.build();
container.addEndpoint(lspWsEndpoint);
});
JettyUtils.initSessionManager(
@@ -11,6 +11,7 @@ Require-Bundle: org.eclipse.core.runtime;visibility:=reexport,
org.apache.commons.jexl,
org.jkiss.utils;visibility:=reexport,
org.jkiss.dbeaver.model.sql;visibility:=reexport,
org.jkiss.dbeaver.model.lsp,
org.jkiss.dbeaver.data.gis,
org.jkiss.bundle.jetty.server;visibility:=reexport,
com.google.gson;visibility:=reexport,
@@ -19,7 +20,8 @@ Require-Bundle: org.eclipse.core.runtime;visibility:=reexport,
org.jkiss.dbeaver.net.ssh,
io.cloudbeaver.model;visibility:=reexport,
io.cloudbeaver.model.cli,
io.cloudbeaver.service.security;visibility:=reexport
io.cloudbeaver.service.security;visibility:=reexport,
org.eclipse.lsp4j.websocket.jakarta
Export-Package: io.cloudbeaver,
io.cloudbeaver.model,
io.cloudbeaver.model.app,
@@ -33,9 +35,11 @@ Export-Package: io.cloudbeaver,
io.cloudbeaver.server.jobs,
io.cloudbeaver.server.servlets,
io.cloudbeaver.server.websockets,
io.cloudbeaver.server.websockets.lsp,
io.cloudbeaver.service,
io.cloudbeaver.service.navigator,
io.cloudbeaver.service.sql
Import-Package: org.slf4j
Import-Package: org.slf4j,
jakarta.websocket
Bundle-Localization: OSGI-INF/l10n/bundle
Automatic-Module-Name: io.cloudbeaver.server
@@ -30,12 +30,12 @@ import java.util.concurrent.CopyOnWriteArrayList;
public class CBJettyWebSocketManager {
private static final Log log = Log.getLog(CBJettyWebSocketManager.class);
private static final Map<String, List<CBEventsWebSocket>> socketBySessionId = new ConcurrentHashMap<>();
private static final Map<String, List<CBAbstractWebSocket>> socketBySessionId = new ConcurrentHashMap<>();
private CBJettyWebSocketManager() {
}
public static void registerWebSocket(@NotNull String webSessionId, @NotNull CBEventsWebSocket webSocket) {
public static void registerWebSocket(@NotNull String webSessionId, @NotNull CBAbstractWebSocket webSocket) {
socketBySessionId.computeIfAbsent(webSessionId, key -> new CopyOnWriteArrayList<>()).add(webSocket);
}
@@ -57,7 +57,7 @@ public class CBJettyWebSocketManager {
entry -> {
var sessionId = entry.getKey();
var webSockets = entry.getValue();
for (CBEventsWebSocket webSocket : webSockets) {
for (CBAbstractWebSocket webSocket : webSockets) {
try {
webSocket.getSession().getBasicRemote().sendPing(
ByteBuffer.wrap("cb-ping".getBytes(StandardCharsets.UTF_8))
@@ -0,0 +1,46 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2026 DBeaver Corp
*
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of DBeaver Corp and its suppliers, if any.
* The intellectual and technical concepts contained
* herein are proprietary to DBeaver Corp and its suppliers
* and may be covered by U.S. and Foreign Patents,
* patents in process, and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from DBeaver Corp.
*/
package io.cloudbeaver.server.websockets.lsp;
import io.cloudbeaver.model.session.BaseWebSession;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.model.app.DBPWorkspace;
import org.jkiss.dbeaver.model.auth.impl.AbstractSessionPersistent;
import org.jkiss.dbeaver.model.lsp.DBLServerSessionProvider;
public class LSPWebServerSesssionProvider implements DBLServerSessionProvider {
@NotNull
private final BaseWebSession session;
public LSPWebServerSesssionProvider(@NotNull BaseWebSession session) {
this.session = session;
}
@Nullable
@Override
public AbstractSessionPersistent getSession() {
return session;
}
@NotNull
@Override
public DBPWorkspace getWorkspace() {
return session.getWorkspace();
}
}
@@ -0,0 +1,26 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2026 DBeaver Corp
*
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of DBeaver Corp and its suppliers, if any.
* The intellectual and technical concepts contained
* herein are proprietary to DBeaver Corp and its suppliers
* and may be covered by U.S. and Foreign Patents,
* patents in process, and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from DBeaver Corp.
*/
package io.cloudbeaver.server.websockets.lsp;
import java.time.Duration;
public class LSPWebSocketConstants {
public static final String ENDPOINT_SUFFIX = "ws/lsp";
public static final Duration IDLE_TIMEOUT = Duration.ofMinutes(5);
}
@@ -0,0 +1,66 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2026 DBeaver Corp
*
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of DBeaver Corp and its suppliers, if any.
* The intellectual and technical concepts contained
* herein are proprietary to DBeaver Corp and its suppliers
* and may be covered by U.S. and Foreign Patents,
* patents in process, and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from DBeaver Corp.
*/
package io.cloudbeaver.server.websockets.lsp;
import io.cloudbeaver.model.session.BaseWebSession;
import io.cloudbeaver.server.websockets.CBAbstractWebSocket;
import io.cloudbeaver.server.websockets.CBJettyWebSocketManager;
import io.cloudbeaver.server.websockets.CBWebSocketServerConfigurator;
import jakarta.websocket.CloseReason;
import jakarta.websocket.EndpointConfig;
import jakarta.websocket.Session;
import org.eclipse.lsp4j.jsonrpc.Launcher;
import org.eclipse.lsp4j.services.LanguageClient;
import org.eclipse.lsp4j.websocket.jakarta.WebSocketLauncherBuilder;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.lsp.DBLServer;
public class LSPWebSocketEndpoint extends CBAbstractWebSocket {
private static final Log log = Log.getLog(LSPWebSocketEndpoint.class);
public LSPWebSocketEndpoint() {}
@Override
public void onOpen(Session wsSession, EndpointConfig endpointConfig) {
BaseWebSession webSession = (BaseWebSession) wsSession.getUserProperties()
.get(CBWebSocketServerConfigurator.PROP_WEB_SESSION);
CBJettyWebSocketManager.registerWebSocket(webSession.getSessionId(), this);
wsSession.setMaxIdleTimeout(LSPWebSocketConstants.IDLE_TIMEOUT.toMillis());
wsSession.setMaxTextMessageBufferSize(Integer.MAX_VALUE);
wsSession.setMaxBinaryMessageBufferSize(Integer.MAX_VALUE);
LSPWebServerSesssionProvider sessionProvider = new LSPWebServerSesssionProvider(webSession);
DBLServer server = new DBLServer(sessionProvider);
var builder = new WebSocketLauncherBuilder<LanguageClient>();
builder.setSession(wsSession);
builder.setLocalService(server);
builder.setRemoteInterface(LanguageClient.class);
Launcher<LanguageClient> launcher = builder.create();
server.connect(launcher.getRemoteProxy());
}
@Override
public void onClose(Session session, CloseReason closeReason) {
log.debug("Closing websocket session: " + session.getId());
}
@Override
public void onError(Session session, Throwable thr) {
log.error("LSP WebSocket error", thr);
}
}