From a2aa2e08fd18c710075687f53b88799fcfd79a6c Mon Sep 17 00:00:00 2001 From: Tobias Ortmayr Date: Tue, 25 Aug 2020 09:32:39 +0200 Subject: [PATCH] #96 #94 Cleanup and refactor client-server communication (#73) * #96 #94 Cleanup and refactor client-server communication - Refactor client-server communication into a base protocol and a jsonrpc specific implementation (#94) - Cleanup protocol and implement (previously unused) shutdown method - Add ClientSessionManager to track lifecycle of GLSP client connections (#96) - Add listener-mechanism to react to lifecycle changes (used in DefaultModelStateProvider) - Remove (now obsolete) GLSPClientProxyProvider - Fix wrong version of guava in org.eclipse.glsp.graph pom.xml - Add unique applicationId to InitializeParameters Part of: - eclipse-glsp/glsp/issues/94 - eclipse-glsp/glsp/issues/96 * Fix minors * Adapt copyright headers and fix checkstyle warnings Co-authored-by: Philip Langer --- .../org.eclipse.glsp.api/META-INF/MANIFEST.MF | 7 +- plugins/org.eclipse.glsp.api/pom.xml | 10 -- .../org/eclipse/glsp/api/action/Action.java | 12 ++- .../kind/DisposeClientAction.java} | 18 ++-- ...ntProvider.java => GLSPJsonrpcClient.java} | 22 ++-- ...GLSPServer.java => GLSPJsonrpcServer.java} | 32 +++--- .../api/model/NavigationTargetResolver.java | 2 +- .../api/protocol/ClientSessionListener.java | 35 ++++++ .../api/protocol/ClientSessionManager.java | 35 ++++++ .../api/{jsonrpc => protocol}/GLSPClient.java | 6 +- .../eclipse/glsp/api/protocol/GLSPServer.java | 30 ++++++ .../GLSPServerException.java | 8 +- .../InitializeParameters.java | 11 +- .../api/provider/ContextEditValidator.java | 4 +- .../glsp/api/registry/MapMultiRegistry.java | 2 +- .../glsp/api/registry/MapRegistry.java | 2 +- .../eclipse/glsp/api/utils/LayoutUtil.java | 2 +- .../META-INF/MANIFEST.MF | 2 +- plugins/org.eclipse.glsp.graph/pom.xml | 6 +- .../server/websocket/GLSPServerEndpoint.java | 22 ++-- .../websocket/WebsocketServerLauncher.java | 2 +- .../META-INF/MANIFEST.MF | 5 +- plugins/org.eclipse.glsp.server/pom.xml | 10 ++ .../actionhandler/ClientActionHandler.java | 16 +-- .../DisposeClientActionHandler.java} | 36 +++---- .../glsp/server/di/DefaultGLSPModule.java | 17 ++- .../eclipse/glsp/server}/di/GLSPModule.java | 14 +-- .../glsp/server/di/MultiBindingDefaults.java | 4 +- .../glsp/server}/json/ActionTypeAdapter.java | 2 +- .../glsp/server}/json/GsonConfigurator.java | 2 +- .../jsonrpc/DefaultClientSessionManager.java | 101 ++++++++++++++++++ .../server/jsonrpc/DefaultGLSPServer.java | 86 +++++++++------ .../launch/DefaultGLSPServerLauncher.java | 19 ++-- .../server/launch/GLSPServerLauncher.java | 3 +- .../model/DefaultModelStateProvider.java | 20 +++- .../server/model/JsonFileModelFactory.java | 2 +- .../ChangeBoundsOperationHandler.java | 2 +- .../ChangeRoutingPointsHandler.java | 2 +- .../ReconnectOperationHandler.java | 2 +- 39 files changed, 422 insertions(+), 191 deletions(-) rename plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/{jsonrpc/GLSPClientAware.java => action/kind/DisposeClientAction.java} (71%) rename plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/{GLSPClientProvider.java => GLSPJsonrpcClient.java} (67%) rename plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/{GLSPServer.java => GLSPJsonrpcServer.java} (68%) create mode 100644 plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/ClientSessionListener.java create mode 100644 plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/ClientSessionManager.java rename plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/{jsonrpc => protocol}/GLSPClient.java (83%) create mode 100644 plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/GLSPServer.java rename plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/{jsonrpc => protocol}/GLSPServerException.java (90%) rename plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/{jsonrpc => protocol}/InitializeParameters.java (76%) rename plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/{jsonrpc/DefaultGLSPClientProvider.java => actionhandler/DisposeClientActionHandler.java} (52%) rename plugins/{org.eclipse.glsp.api/src/org/eclipse/glsp/api => org.eclipse.glsp.server/src/org/eclipse/glsp/server}/di/GLSPModule.java (95%) rename plugins/{org.eclipse.glsp.api/src/org/eclipse/glsp/api => org.eclipse.glsp.server/src/org/eclipse/glsp/server}/json/ActionTypeAdapter.java (98%) rename plugins/{org.eclipse.glsp.api/src/org/eclipse/glsp/api => org.eclipse.glsp.server/src/org/eclipse/glsp/server}/json/GsonConfigurator.java (98%) create mode 100644 plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/jsonrpc/DefaultClientSessionManager.java diff --git a/plugins/org.eclipse.glsp.api/META-INF/MANIFEST.MF b/plugins/org.eclipse.glsp.api/META-INF/MANIFEST.MF index 6666ac4a..d8d1c49a 100644 --- a/plugins/org.eclipse.glsp.api/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.glsp.api/META-INF/MANIFEST.MF @@ -10,18 +10,14 @@ Require-Bundle: org.eclipse.lsp4j, org.eclipse.lsp4j.jsonrpc;bundle-version="0.7.0", javax.websocket;bundle-version="1.0.0";visibility:=reexport, org.eclipse.glsp.graph;bundle-version="0.7.0";visibility:=reexport, - com.google.gson, - com.google.inject;bundle-version="3.0.0";visibility:=reexport, - com.google.guava;bundle-version="21.0.0" + com.google.gson Bundle-ClassPath: . Export-Package: org.eclipse.glsp.api.action, org.eclipse.glsp.api.action.kind, org.eclipse.glsp.api.configuration, - org.eclipse.glsp.api.di, org.eclipse.glsp.api.diagram, org.eclipse.glsp.api.factory, org.eclipse.glsp.api.handler, - org.eclipse.glsp.api.json, org.eclipse.glsp.api.jsonrpc, org.eclipse.glsp.api.labeledit, org.eclipse.glsp.api.layout, @@ -29,6 +25,7 @@ Export-Package: org.eclipse.glsp.api.action, org.eclipse.glsp.api.model, org.eclipse.glsp.api.operation, org.eclipse.glsp.api.operation.kind, + org.eclipse.glsp.api.protocol, org.eclipse.glsp.api.provider, org.eclipse.glsp.api.registry, org.eclipse.glsp.api.types, diff --git a/plugins/org.eclipse.glsp.api/pom.xml b/plugins/org.eclipse.glsp.api/pom.xml index d0078167..9b15ff7c 100644 --- a/plugins/org.eclipse.glsp.api/pom.xml +++ b/plugins/org.eclipse.glsp.api/pom.xml @@ -66,16 +66,6 @@ org.eclipse.lsp4j.jsonrpc 0.9.0 - - com.google.inject - guice - 3.0 - - - com.google.inject.extensions - guice-multibindings - 3.0 - org.eclipse.glsp org.eclipse.glsp.graph diff --git a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/action/Action.java b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/action/Action.java index 991e2fef..9829b0b9 100644 --- a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/action/Action.java +++ b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/action/Action.java @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2019 EclipseSource and others. + * Copyright (c) 2019-2020 EclipseSource and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -39,6 +39,7 @@ public static class Kind { public static final String CLEAR_MARKERS = "clearMarkers"; public static final String COMPUTED_BOUNDS = "computedBounds"; public static final String CUT_ACTION = "cut"; + public static final String DISPOSE_CLIENT = "disposeClient"; public static final String EXECUTE_OPERATION = "executeOperation"; public static final String EXECUTE_SERVER_COMMAND = "executeServerCommand"; public static final String EXPORT_SVG = "exportSvg"; @@ -55,6 +56,7 @@ public static class Kind { public static final String REQUEST_OPERATIONS = "requestOperations"; public static final String REQUEST_POPUP_MODEL = "requestPopupModel"; public static final String REQUEST_TYPE_HINTS = "requestTypeHints"; + public static final String RESOLVE_NAVIGATION_TARGET = "resolveNavigationTarget"; public static final String SAVE_MODEL = "saveModel"; public static final String SELECT = "selectElement"; public static final String SELECT_ALL = "allSelected"; @@ -64,6 +66,7 @@ public static class Kind { public static final String SET_CLIPBOARD_DATA = "setClipboardData"; public static final String SET_CONTEXT_ACTIONS = "setContextActions"; public static final String SET_DIRTY_STATE = "setDirtyState"; + public static final String SET_EDIT_MODE = "setEditMode"; public static final String SET_EDIT_VALIDATION_RESULT = "setEditValidationResult"; public static final String SET_LABEL_EDIT_VALIDATION_RESULT_ACTION = "setLabelEditValidationResult"; public static final String SET_LAYERS = "setLayers"; @@ -71,14 +74,13 @@ public static class Kind { public static final String SET_MODEL = "setModel"; public static final String SET_NAVIGATION_TARGETS = "setNavigationTargets"; public static final String SET_POPUP_MODEL = "setPopupModel"; + public static final String SET_RESOLVED_NAVIGATION_TARGET = "setResolvedNavigationTarget"; public static final String SET_TYPE_HINTS = "setTypeHints"; - public static final String TRIGGER_NODE_CREATION = "triggerNodeCreation"; public static final String TRIGGER_EDGE_CREATION = "triggerEdgeCreation"; + public static final String TRIGGER_NODE_CREATION = "triggerNodeCreation"; public static final String UNDO = "glspUndo"; public static final String UPDATE_MODEL = "updateModel"; public static final String VALIDATE_LABEL_EDIT_ACTION = "validateLabelEdit"; - public static final String RESOLVE_NAVIGATION_TARGET = "resolveNavigationTarget"; - public static final String SET_RESOLVED_NAVIGATION_TARGET = "setResolvedNavigationTarget"; - public static final String SET_EDIT_MODE = "setEditMode"; } + } diff --git a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPClientAware.java b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/action/kind/DisposeClientAction.java similarity index 71% rename from plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPClientAware.java rename to plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/action/kind/DisposeClientAction.java index 54f12983..a079b4a2 100644 --- a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPClientAware.java +++ b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/action/kind/DisposeClientAction.java @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2019 EclipseSource and others. +/******************************************************************************** + * Copyright (c) 2020 EclipseSource and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -12,9 +12,15 @@ * https://www.gnu.org/software/classpath/license.html. * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - ******************************************************************************/ -package org.eclipse.glsp.api.jsonrpc; + ********************************************************************************/ +package org.eclipse.glsp.api.action.kind; + +import org.eclipse.glsp.api.action.Action; + +public class DisposeClientAction extends Action { + + public DisposeClientAction() { + super(Action.Kind.DISPOSE_CLIENT); + } -public interface GLSPClientAware { - void connect(GLSPClient client); } diff --git a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPClientProvider.java b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPJsonrpcClient.java similarity index 67% rename from plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPClientProvider.java rename to plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPJsonrpcClient.java index 3fdfff73..9db53a0b 100644 --- a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPClientProvider.java +++ b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPJsonrpcClient.java @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2019 EclipseSource and others. +/******************************************************************************** + * Copyright (c) 2020 EclipseSource and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -12,17 +12,17 @@ * https://www.gnu.org/software/classpath/license.html. * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - ******************************************************************************/ + ********************************************************************************/ package org.eclipse.glsp.api.jsonrpc; -/** - * A registry to associate & retrieve a {@link GLSPClient} from a - * clientId. - */ -public interface GLSPClientProvider { - void register(String clientId, GLSPClient client); +import org.eclipse.glsp.api.action.ActionMessage; +import org.eclipse.glsp.api.protocol.GLSPClient; +import org.eclipse.lsp4j.jsonrpc.services.JsonNotification; - GLSPClient resolve(String clientId); +public interface GLSPJsonrpcClient extends GLSPClient { + + @Override + @JsonNotification("process") + void process(ActionMessage message); - void remove(String clientId); } diff --git a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPServer.java b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPJsonrpcServer.java similarity index 68% rename from plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPServer.java rename to plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPJsonrpcServer.java index 6dd7fde1..0983c0e4 100644 --- a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPServer.java +++ b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPJsonrpcServer.java @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2019 EclipseSource and others. +/******************************************************************************** + * Copyright (c) 2020 EclipseSource and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -12,33 +12,27 @@ * https://www.gnu.org/software/classpath/license.html. * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - ******************************************************************************/ + ********************************************************************************/ package org.eclipse.glsp.api.jsonrpc; import java.util.concurrent.CompletableFuture; import org.eclipse.glsp.api.action.ActionMessage; -import org.eclipse.glsp.api.types.ServerStatus; +import org.eclipse.glsp.api.protocol.GLSPServer; +import org.eclipse.glsp.api.protocol.InitializeParameters; import org.eclipse.lsp4j.jsonrpc.services.JsonNotification; import org.eclipse.lsp4j.jsonrpc.services.JsonRequest; -public interface GLSPServer extends GLSPClientAware { - - public interface Provider { - GLSPServer getGraphicalLanguageServer(String clientId); - } - - @JsonRequest("initialize") +public interface GLSPJsonrpcServer extends GLSPServer { + @Override + @JsonRequest CompletableFuture initialize(InitializeParameters params); - @JsonNotification("process") + @Override + @JsonNotification void process(ActionMessage message); - @JsonRequest("shutdown") - CompletableFuture shutdown(); - - @JsonNotification("exit") - void exit(String clientId); - - ServerStatus getStatus(); + @Override + @JsonRequest + CompletableFuture shutdown(); } diff --git a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/model/NavigationTargetResolver.java b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/model/NavigationTargetResolver.java index 97a6d771..a8fd8e9a 100644 --- a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/model/NavigationTargetResolver.java +++ b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/model/NavigationTargetResolver.java @@ -63,7 +63,7 @@ default void addError(final String message, final Map args) { args.put(ERROR, message); } - public class NullImpl implements NavigationTargetResolver { + class NullImpl implements NavigationTargetResolver { @Override public NavigationTargetResolution resolve(final NavigationTarget navigationTarget, final GraphicalModelState modelState) { diff --git a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/ClientSessionListener.java b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/ClientSessionListener.java new file mode 100644 index 00000000..7771549b --- /dev/null +++ b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/ClientSessionListener.java @@ -0,0 +1,35 @@ +/******************************************************************************** + * Copyright (c) 2020 EclipseSource and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ +package org.eclipse.glsp.api.protocol; + +public interface ClientSessionListener { + + default void clientConnected(final GLSPClient client) { + // No-op as default. This enables partial interface implementation. + } + + default void sessionCreated(final String clientId, final GLSPClient client) { + // No-op as default. This enables partial interface implementation. + } + + default void sessionClosed(final String clientId, final GLSPClient client) { + // No-op as default. This enables partial interface implementation. + } + + default void clientDisconnected(final GLSPClient client) { + // No-op as default. This enables partial interface implementation. + } +} diff --git a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/ClientSessionManager.java b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/ClientSessionManager.java new file mode 100644 index 00000000..628d1028 --- /dev/null +++ b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/ClientSessionManager.java @@ -0,0 +1,35 @@ +/******************************************************************************** + * Copyright (c) 2020 EclipseSource and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ +package org.eclipse.glsp.api.protocol; + +import java.util.Optional; + +public interface ClientSessionManager { + + boolean connectClient(GLSPClient client); + + boolean createClientSession(GLSPClient glspClient, String clientId); + + boolean disposeClientSession(String clientId); + + boolean disconnectClient(GLSPClient client); + + boolean addListener(ClientSessionListener listener); + + boolean removeListener(ClientSessionListener listener); + + Optional resolve(String clientId); +} diff --git a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPClient.java b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/GLSPClient.java similarity index 83% rename from plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPClient.java rename to plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/GLSPClient.java index ce90436e..146f6bce 100644 --- a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPClient.java +++ b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/GLSPClient.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019 EclipseSource and others. + * Copyright (c) 2019-2020 EclipseSource and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -13,13 +13,11 @@ * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ******************************************************************************/ -package org.eclipse.glsp.api.jsonrpc; +package org.eclipse.glsp.api.protocol; import org.eclipse.glsp.api.action.ActionMessage; -import org.eclipse.lsp4j.jsonrpc.services.JsonNotification; public interface GLSPClient { - @JsonNotification("process") void process(ActionMessage message); } diff --git a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/GLSPServer.java b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/GLSPServer.java new file mode 100644 index 00000000..63a67a0d --- /dev/null +++ b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/GLSPServer.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2019-2020 EclipseSource and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ******************************************************************************/ +package org.eclipse.glsp.api.protocol; + +import java.util.concurrent.CompletableFuture; + +import org.eclipse.glsp.api.action.ActionMessage; + +public interface GLSPServer { + CompletableFuture initialize(InitializeParameters params); + + void process(ActionMessage message); + + CompletableFuture shutdown(); + + void connect(T client); +} diff --git a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPServerException.java b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/GLSPServerException.java similarity index 90% rename from plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPServerException.java rename to plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/GLSPServerException.java index e90af3f2..a8eb9f36 100644 --- a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/GLSPServerException.java +++ b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/GLSPServerException.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019 EclipseSource and others. + * Copyright (c) 2019-2020 EclipseSource and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -13,7 +13,7 @@ * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ******************************************************************************/ -package org.eclipse.glsp.api.jsonrpc; +package org.eclipse.glsp.api.protocol; import java.util.NoSuchElementException; import java.util.Optional; @@ -51,7 +51,7 @@ public GLSPServerException(final String message, final Throwable throwable) { * @return the value * @throws GLSPServerException if value not present */ - public static T getOrThrow(Optional optional, String exceptionMessage) { + public static T getOrThrow(final Optional optional, final String exceptionMessage) { try { return optional.get(); } catch (NoSuchElementException ex) { @@ -71,7 +71,7 @@ public static T getOrThrow(Optional optional, String exceptionMessage) { * @throws GLSPServerException if value not present or could not an instance of * T */ - public static T getOrThrow(Optional optional, Class clazz, String exceptionMessage) { + public static T getOrThrow(final Optional optional, final Class clazz, final String exceptionMessage) { try { Object toCast = optional.get(); return clazz.cast(toCast); diff --git a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/InitializeParameters.java b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/InitializeParameters.java similarity index 76% rename from plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/InitializeParameters.java rename to plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/InitializeParameters.java index cd9160d1..836a3d8a 100644 --- a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/jsonrpc/InitializeParameters.java +++ b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/protocol/InitializeParameters.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019 EclipseSource and others. + * Copyright (c) 2019-2020 EclipseSource and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -13,19 +13,24 @@ * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ******************************************************************************/ -package org.eclipse.glsp.api.jsonrpc; +package org.eclipse.glsp.api.protocol; import org.eclipse.lsp4j.jsonrpc.json.adapters.JsonElementTypeAdapter; import com.google.gson.annotations.JsonAdapter; public class InitializeParameters { + private String applicationId; @JsonAdapter(JsonElementTypeAdapter.Factory.class) private Object options; public Object getOptions() { return options; } - public void setOptions(Object options) { this.options = options; } + public void setOptions(final Object options) { this.options = options; } + + public String getApplicationId() { return applicationId; } + + public void setApplicationId(final String applicationId) { this.applicationId = applicationId; } @Override public String toString() { diff --git a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/provider/ContextEditValidator.java b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/provider/ContextEditValidator.java index f3e10602..ba15cc2f 100644 --- a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/provider/ContextEditValidator.java +++ b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/provider/ContextEditValidator.java @@ -23,8 +23,8 @@ public interface ContextEditValidator { String getContextId(); - ValidationStatus validate(final RequestEditValidationAction action, - final GraphicalModelState modelState); + ValidationStatus validate(RequestEditValidationAction action, + GraphicalModelState modelState); default boolean handles(final String contextId) { return getContextId().equals(contextId); diff --git a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/registry/MapMultiRegistry.java b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/registry/MapMultiRegistry.java index 515e68bc..61b7a2c3 100644 --- a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/registry/MapMultiRegistry.java +++ b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/registry/MapMultiRegistry.java @@ -22,7 +22,7 @@ import java.util.Map; import java.util.stream.Collectors; -import org.eclipse.glsp.api.jsonrpc.GLSPServerException; +import org.eclipse.glsp.api.protocol.GLSPServerException; public abstract class MapMultiRegistry implements MultiRegistry { protected Map> elements; diff --git a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/registry/MapRegistry.java b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/registry/MapRegistry.java index 72c42a6c..4c3a47fc 100644 --- a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/registry/MapRegistry.java +++ b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/registry/MapRegistry.java @@ -21,7 +21,7 @@ import java.util.Optional; import java.util.Set; -import org.eclipse.glsp.api.jsonrpc.GLSPServerException; +import org.eclipse.glsp.api.protocol.GLSPServerException; public abstract class MapRegistry implements Registry { protected Map elements; diff --git a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/utils/LayoutUtil.java b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/utils/LayoutUtil.java index 0ce3f5d1..1428ced3 100644 --- a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/utils/LayoutUtil.java +++ b/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/utils/LayoutUtil.java @@ -15,7 +15,7 @@ ******************************************************************************/ package org.eclipse.glsp.api.utils; -import static org.eclipse.glsp.api.jsonrpc.GLSPServerException.getOrThrow; +import static org.eclipse.glsp.api.protocol.GLSPServerException.getOrThrow; import java.util.Optional; diff --git a/plugins/org.eclipse.glsp.graph/META-INF/MANIFEST.MF b/plugins/org.eclipse.glsp.graph/META-INF/MANIFEST.MF index 99b4579e..d9b2fb18 100644 --- a/plugins/org.eclipse.glsp.graph/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.glsp.graph/META-INF/MANIFEST.MF @@ -10,7 +10,7 @@ Require-Bundle: org.eclipse.emf.common;bundle-version="2.15.0", com.google.gson, org.eclipse.emf.ecore;bundle-version="2.15.0";visibility:=reexport, org.apache.log4j;bundle-version="1.2.15";visibility:=reexport, - com.google.guava;bundle-version="21.0.0" + com.google.guava;bundle-version="21.0.0";visibility:=reexport Export-Package: org.eclipse.glsp.graph, org.eclipse.glsp.graph, org.eclipse.glsp.graph.builder, diff --git a/plugins/org.eclipse.glsp.graph/pom.xml b/plugins/org.eclipse.glsp.graph/pom.xml index 3230988e..6b15c625 100644 --- a/plugins/org.eclipse.glsp.graph/pom.xml +++ b/plugins/org.eclipse.glsp.graph/pom.xml @@ -55,9 +55,9 @@ - com.google.inject - guice - 3.0 + com.google.guava + guava + 27.1-jre org.eclipse.emf diff --git a/plugins/org.eclipse.glsp.server.websocket/src/org/eclipse/glsp/server/websocket/GLSPServerEndpoint.java b/plugins/org.eclipse.glsp.server.websocket/src/org/eclipse/glsp/server/websocket/GLSPServerEndpoint.java index 386bf13c..4eb67044 100644 --- a/plugins/org.eclipse.glsp.server.websocket/src/org/eclipse/glsp/server/websocket/GLSPServerEndpoint.java +++ b/plugins/org.eclipse.glsp.server.websocket/src/org/eclipse/glsp/server/websocket/GLSPServerEndpoint.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019 EclipseSource and others. + * Copyright (c) 2019-2020 EclipseSource and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -20,33 +20,33 @@ import javax.websocket.EndpointConfig; import javax.websocket.Session; -import org.eclipse.glsp.api.json.GsonConfigurator; -import org.eclipse.glsp.api.jsonrpc.GLSPClient; -import org.eclipse.glsp.api.jsonrpc.GLSPClientAware; -import org.eclipse.glsp.api.jsonrpc.GLSPServer; +import org.eclipse.glsp.api.jsonrpc.GLSPJsonrpcClient; +import org.eclipse.glsp.api.jsonrpc.GLSPJsonrpcServer; +import org.eclipse.glsp.api.protocol.GLSPServer; +import org.eclipse.glsp.server.json.GsonConfigurator; import org.eclipse.lsp4j.jsonrpc.Launcher.Builder; import org.eclipse.lsp4j.websocket.WebSocketEndpoint; import com.google.inject.Inject; -public class GLSPServerEndpoint extends WebSocketEndpoint { +public class GLSPServerEndpoint extends WebSocketEndpoint { public static final int MAX_TEXT_MESSAGE_BUFFER_SIZE = 8388608; @Inject - private GLSPServer glspServer; + private GLSPServer glspServer; @Inject private GsonConfigurator gsonConfigurator; @Override - protected void configure(final Builder builder) { + protected void configure(final Builder builder) { builder.setLocalService(glspServer); - builder.setRemoteInterface(GLSPClient.class); + builder.setRemoteInterface(GLSPJsonrpcClient.class); builder.configureGson(gsonConfigurator::configureGsonBuilder); } @Override - protected void connect(final Collection localServices, final GLSPClient remoteProxy) { - localServices.stream().filter(GLSPClientAware.class::isInstance).map(GLSPClientAware.class::cast) + protected void connect(final Collection localServices, final GLSPJsonrpcClient remoteProxy) { + localServices.stream().filter(GLSPJsonrpcServer.class::isInstance).map(GLSPJsonrpcServer.class::cast) .forEach(ca -> ca.connect(remoteProxy)); } diff --git a/plugins/org.eclipse.glsp.server.websocket/src/org/eclipse/glsp/server/websocket/WebsocketServerLauncher.java b/plugins/org.eclipse.glsp.server.websocket/src/org/eclipse/glsp/server/websocket/WebsocketServerLauncher.java index 617c106c..7c5039e9 100644 --- a/plugins/org.eclipse.glsp.server.websocket/src/org/eclipse/glsp/server/websocket/WebsocketServerLauncher.java +++ b/plugins/org.eclipse.glsp.server.websocket/src/org/eclipse/glsp/server/websocket/WebsocketServerLauncher.java @@ -22,7 +22,7 @@ import javax.websocket.server.ServerEndpointConfig; import org.apache.log4j.Logger; -import org.eclipse.glsp.api.di.GLSPModule; +import org.eclipse.glsp.server.di.GLSPModule; import org.eclipse.glsp.server.launch.GLSPServerLauncher; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; diff --git a/plugins/org.eclipse.glsp.server/META-INF/MANIFEST.MF b/plugins/org.eclipse.glsp.server/META-INF/MANIFEST.MF index 1cd0c668..b8d0e47b 100644 --- a/plugins/org.eclipse.glsp.server/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.glsp.server/META-INF/MANIFEST.MF @@ -12,13 +12,14 @@ Require-Bundle: org.eclipse.glsp.api;bundle-version="0.7.0";visibility:=reexport com.google.gson;bundle-version="2.8.2", org.eclipse.lsp4j;bundle-version="0.7.0", org.eclipse.lsp4j.jsonrpc, - com.google.guava;bundle-version="21.0.0", - org.apache.commons.cli;bundle-version="1.4.0";visibility:=reexport + org.apache.commons.cli;bundle-version="1.4.0";visibility:=reexport, + com.google.inject;bundle-version="3.0.0";visibility:=reexport Import-Package: com.google.inject.multibindings;version="1.3.0" Export-Package: org.eclipse.glsp.server.actionhandler, org.eclipse.glsp.server.command, org.eclipse.glsp.server.di, org.eclipse.glsp.server.factory, + org.eclipse.glsp.server.json, org.eclipse.glsp.server.jsonrpc, org.eclipse.glsp.server.launch, org.eclipse.glsp.server.model, diff --git a/plugins/org.eclipse.glsp.server/pom.xml b/plugins/org.eclipse.glsp.server/pom.xml index be06e432..7c22431d 100644 --- a/plugins/org.eclipse.glsp.server/pom.xml +++ b/plugins/org.eclipse.glsp.server/pom.xml @@ -59,6 +59,16 @@ org.eclipse.glsp.api 0.8.0-SNAPSHOT + + com.google.inject + guice + 3.0 + + + com.google.inject.extensions + guice-multibindings + 3.0 + org.eclipse.emf org.eclipse.emf.ecore.change diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actionhandler/ClientActionHandler.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actionhandler/ClientActionHandler.java index 33f4ea77..c25b68d5 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actionhandler/ClientActionHandler.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actionhandler/ClientActionHandler.java @@ -23,9 +23,10 @@ import org.eclipse.glsp.api.action.Action; import org.eclipse.glsp.api.action.ActionMessage; import org.eclipse.glsp.api.handler.ActionHandler; -import org.eclipse.glsp.api.jsonrpc.GLSPClient; -import org.eclipse.glsp.api.jsonrpc.GLSPClientProvider; import org.eclipse.glsp.api.model.GraphicalModelState; +import org.eclipse.glsp.api.protocol.ClientSessionManager; +import org.eclipse.glsp.api.protocol.GLSPClient; +import org.eclipse.glsp.api.protocol.GLSPServerException; import com.google.inject.Inject; import com.google.inject.name.Named; @@ -33,8 +34,8 @@ public class ClientActionHandler implements ActionHandler { public static final String CLIENT_ACTIONS = "ClientActionHandler"; - @Inject - protected GLSPClientProvider clientProvider; + @Inject() + protected ClientSessionManager sessionManager; private final List> handledActionTypes; @@ -53,11 +54,10 @@ public List execute(final Action action, final GraphicalModelState model } protected void send(final String clientId, final Action action) { - GLSPClient client = clientProvider.resolve(clientId); - if (client == null) { - throw new IllegalStateException("Unable to send a message to Client ID:" + clientId + GLSPClient client = GLSPServerException.getOrThrow(sessionManager.resolve(clientId), + "Unable to send a message to Client ID:" + clientId + ". This ID does not match any known client (Client disconnected or not initialized yet?)"); - } + ActionMessage message = new ActionMessage(clientId, action); client.process(message); } diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/jsonrpc/DefaultGLSPClientProvider.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actionhandler/DisposeClientActionHandler.java similarity index 52% rename from plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/jsonrpc/DefaultGLSPClientProvider.java rename to plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actionhandler/DisposeClientActionHandler.java index 97a808e6..2daac645 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/jsonrpc/DefaultGLSPClientProvider.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actionhandler/DisposeClientActionHandler.java @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2019 EclipseSource and others. + * Copyright (c) 2020 EclipseSource and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -13,34 +13,26 @@ * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -package org.eclipse.glsp.server.jsonrpc; +package org.eclipse.glsp.server.actionhandler; -import java.util.HashMap; -import java.util.Map; +import java.util.List; -import org.eclipse.glsp.api.jsonrpc.GLSPClient; -import org.eclipse.glsp.api.jsonrpc.GLSPClientProvider; +import org.eclipse.glsp.api.action.Action; +import org.eclipse.glsp.api.action.kind.DisposeClientAction; +import org.eclipse.glsp.api.model.GraphicalModelState; +import org.eclipse.glsp.api.protocol.ClientSessionManager; -import com.google.inject.Singleton; +import com.google.inject.Inject; -@Singleton -public class DefaultGLSPClientProvider implements GLSPClientProvider { +public class DisposeClientActionHandler extends BasicActionHandler { - private final Map clients = new HashMap<>(); + @Inject() + protected ClientSessionManager sessionManager; @Override - public void register(final String clientId, final GLSPClient client) { - clients.put(clientId, client); - } - - @Override - public GLSPClient resolve(final String clientId) { - return clients.get(clientId); - } - - @Override - public void remove(final String clientId) { - clients.remove(clientId); + protected List executeAction(final DisposeClientAction action, final GraphicalModelState modelState) { + sessionManager.disposeClientSession(modelState.getClientId()); + return none(); } } diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/di/DefaultGLSPModule.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/di/DefaultGLSPModule.java index 4787bbc2..65962a0d 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/di/DefaultGLSPModule.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/di/DefaultGLSPModule.java @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2019 EclipseSource and others. + * Copyright (c) 2019-2020 EclipseSource and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -21,15 +21,14 @@ import org.eclipse.glsp.api.action.Action; import org.eclipse.glsp.api.action.ActionDispatcher; -import org.eclipse.glsp.api.di.GLSPModule; import org.eclipse.glsp.api.diagram.DiagramConfiguration; import org.eclipse.glsp.api.factory.GraphGsonConfiguratorFactory; import org.eclipse.glsp.api.handler.ActionHandler; import org.eclipse.glsp.api.handler.OperationHandler; import org.eclipse.glsp.api.handler.ServerCommandHandler; -import org.eclipse.glsp.api.jsonrpc.GLSPClientProvider; -import org.eclipse.glsp.api.jsonrpc.GLSPServer; import org.eclipse.glsp.api.model.ModelStateProvider; +import org.eclipse.glsp.api.protocol.ClientSessionManager; +import org.eclipse.glsp.api.protocol.GLSPServer; import org.eclipse.glsp.api.provider.ContextActionsProvider; import org.eclipse.glsp.api.provider.ContextEditValidator; import org.eclipse.glsp.api.provider.NavigationTargetProvider; @@ -44,7 +43,7 @@ import org.eclipse.glsp.api.registry.ServerCommandHandlerRegistry; import org.eclipse.glsp.server.action.DefaultActionDispatcher; import org.eclipse.glsp.server.factory.DefaultGraphGsonConfiguratorFactory; -import org.eclipse.glsp.server.jsonrpc.DefaultGLSPClientProvider; +import org.eclipse.glsp.server.jsonrpc.DefaultClientSessionManager; import org.eclipse.glsp.server.jsonrpc.DefaultGLSPServer; import org.eclipse.glsp.server.model.DefaultModelStateProvider; import org.eclipse.glsp.server.provider.DefaultToolPaletteItemProvider; @@ -125,11 +124,6 @@ protected Class bindActionDispatcher() { return DefaultActionDispatcher.class; } - @Override - protected Class bindGSLPClientProvider() { - return DefaultGLSPClientProvider.class; - } - @Override protected Class bindToolPaletteItemProvider() { return DefaultToolPaletteItemProvider.class; @@ -175,4 +169,7 @@ protected Class bindServerCommandHandler return DIServerCommandHandlerRegistry.class; } + @Override + protected ClientSessionManager getClientSessionManager() { return DefaultClientSessionManager.INSTANCE; } + } diff --git a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/di/GLSPModule.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/di/GLSPModule.java similarity index 95% rename from plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/di/GLSPModule.java rename to plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/di/GLSPModule.java index 31ffb718..626a45bb 100644 --- a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/di/GLSPModule.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/di/GLSPModule.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019 EclipseSource and others. + * Copyright (c) 2019-2020 EclipseSource and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -13,7 +13,7 @@ * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ******************************************************************************/ -package org.eclipse.glsp.api.di; +package org.eclipse.glsp.server.di; import java.util.Optional; @@ -22,13 +22,13 @@ import org.eclipse.glsp.api.factory.GraphGsonConfiguratorFactory; import org.eclipse.glsp.api.factory.ModelFactory; import org.eclipse.glsp.api.factory.PopupModelFactory; -import org.eclipse.glsp.api.jsonrpc.GLSPClientProvider; -import org.eclipse.glsp.api.jsonrpc.GLSPServer; import org.eclipse.glsp.api.labeledit.LabelEditValidator; import org.eclipse.glsp.api.layout.ILayoutEngine; import org.eclipse.glsp.api.markers.ModelValidator; import org.eclipse.glsp.api.model.ModelStateProvider; import org.eclipse.glsp.api.model.NavigationTargetResolver; +import org.eclipse.glsp.api.protocol.ClientSessionManager; +import org.eclipse.glsp.api.protocol.GLSPServer; import org.eclipse.glsp.api.provider.CommandPaletteActionProvider; import org.eclipse.glsp.api.provider.ContextMenuItemProvider; import org.eclipse.glsp.api.provider.ToolPaletteItemProvider; @@ -59,13 +59,12 @@ protected void configure() { bind(LabelEditValidator.class).to(bindLabelEditValidator()); bind(ModelStateProvider.class).to(bindModelStateProvider()); bind(GraphGsonConfiguratorFactory.class).to(bindGraphGsonConfiguratorFactory()); - bind(GLSPClientProvider.class).to(bindGSLPClientProvider()); bind(ServerConfiguration.class).to(bindServerConfiguration()).in(Singleton.class); bind(ToolPaletteItemProvider.class).to(bindToolPaletteItemProvider()); bind(CommandPaletteActionProvider.class).to(bindCommandPaletteActionProvider()); bind(ContextMenuItemProvider.class).to(bindContextMenuItemProvider()); bind(NavigationTargetResolver.class).to(bindNavigationTargetResolver()); - + bind(ClientSessionManager.class).toInstance(getClientSessionManager()); // Configure set suppliers bind(ActionRegistry.class).to(bindActionRegistry()).in(Singleton.class); bind(ActionHandlerRegistry.class).to(bindActionHandlerRegistry()).in(Singleton.class); @@ -75,11 +74,12 @@ protected void configure() { bind(NavigationTargetProviderRegistry.class).to(bindNavigationTargetProviderRegistry()).in(Singleton.class); bind(ContextEditValidatorRegistry.class).to(bindContextEditValidatorRegistry()).in(Singleton.class); bind(ServerCommandHandlerRegistry.class).to(bindServerCommandHandlerRegistry()).in(Singleton.class); + // Configure Optional Bindings (Bindings that cannot be bound to a NullImpl) Optional.ofNullable(bindGraphExtension()).ifPresent(ext -> bind(GraphExtension.class).to(ext)); } - protected abstract Class bindGSLPClientProvider(); + protected abstract ClientSessionManager getClientSessionManager(); protected abstract Class bindModelStateProvider(); diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/di/MultiBindingDefaults.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/di/MultiBindingDefaults.java index 18c52104..04af891b 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/di/MultiBindingDefaults.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/di/MultiBindingDefaults.java @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2019 EclipseSource and others. + * Copyright (c) 2019-2020 EclipseSource and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -48,6 +48,7 @@ import org.eclipse.glsp.api.handler.OperationHandler; import org.eclipse.glsp.server.actionhandler.ClientActionHandler; import org.eclipse.glsp.server.actionhandler.ComputedBoundsActionHandler; +import org.eclipse.glsp.server.actionhandler.DisposeClientActionHandler; import org.eclipse.glsp.server.actionhandler.ExecuteServerCommandActionHandler; import org.eclipse.glsp.server.actionhandler.OperationActionHandler; import org.eclipse.glsp.server.actionhandler.RequestClipboardDataActionHandler; @@ -108,6 +109,7 @@ private MultiBindingDefaults() {} public static final List> DEFAULT_ACTION_HANDLERS = Lists.newArrayList( ClientActionHandler.class, ComputedBoundsActionHandler.class, + DisposeClientActionHandler.class, OperationActionHandler.class, RequestModelActionHandler.class, RequestPopupModelActionHandler.class, diff --git a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/json/ActionTypeAdapter.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/json/ActionTypeAdapter.java similarity index 98% rename from plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/json/ActionTypeAdapter.java rename to plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/json/ActionTypeAdapter.java index 6efb9164..fd6f660c 100644 --- a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/json/ActionTypeAdapter.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/json/ActionTypeAdapter.java @@ -13,7 +13,7 @@ * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -package org.eclipse.glsp.api.json; +package org.eclipse.glsp.server.json; import java.lang.reflect.Constructor; import java.util.HashMap; diff --git a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/json/GsonConfigurator.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/json/GsonConfigurator.java similarity index 98% rename from plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/json/GsonConfigurator.java rename to plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/json/GsonConfigurator.java index 431c4632..810c1183 100644 --- a/plugins/org.eclipse.glsp.api/src/org/eclipse/glsp/api/json/GsonConfigurator.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/json/GsonConfigurator.java @@ -13,7 +13,7 @@ * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ******************************************************************************/ -package org.eclipse.glsp.api.json; +package org.eclipse.glsp.server.json; import org.eclipse.glsp.api.factory.GraphGsonConfiguratorFactory; import org.eclipse.glsp.api.registry.ActionRegistry; diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/jsonrpc/DefaultClientSessionManager.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/jsonrpc/DefaultClientSessionManager.java new file mode 100644 index 00000000..a2ac8ec2 --- /dev/null +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/jsonrpc/DefaultClientSessionManager.java @@ -0,0 +1,101 @@ +/******************************************************************************** + * Copyright (c) 2020 EclipseSource and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ +package org.eclipse.glsp.server.jsonrpc; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import org.eclipse.glsp.api.protocol.ClientSessionListener; +import org.eclipse.glsp.api.protocol.ClientSessionManager; +import org.eclipse.glsp.api.protocol.GLSPClient; + +public final class DefaultClientSessionManager implements ClientSessionManager { + + private final Set clients = new HashSet<>(); + private final Set listeners = new LinkedHashSet<>(); + private final Map clientSessions = new HashMap<>(); + + public static final DefaultClientSessionManager INSTANCE = new DefaultClientSessionManager(); + + private DefaultClientSessionManager() {} + + @Override + public synchronized boolean connectClient(final GLSPClient client) { + boolean success = clients.add(client); + if (success) { + listeners.forEach(listener -> listener.clientConnected(client)); + } + return success; + } + + @Override + public synchronized boolean createClientSession(final GLSPClient client, final String clientId) { + connectClient(client); + boolean success = clientSessions.putIfAbsent(clientId, client) == null; + if (success) { + listeners.forEach(listener -> listener.sessionCreated(clientId, client)); + } + return success; + } + + @Override + public synchronized boolean disposeClientSession(final String clientId) { + GLSPClient client = clientSessions.remove(clientId); + if (client != null) { + listeners.forEach(listener -> listener.sessionClosed(clientId, client)); + return true; + } + return false; + } + + @Override + public synchronized boolean disconnectClient(final GLSPClient client) { + if (clients.contains(client)) { + List sessionsToDisconnect = clientSessions.entrySet().stream() + .filter(entry -> entry.getValue().equals(client)) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + + sessionsToDisconnect.forEach(this::disposeClientSession); + this.clients.remove(client); + this.listeners.forEach(listener -> listener.clientDisconnected(client)); + return true; + } + return false; + } + + @Override + public boolean addListener(final ClientSessionListener listener) { + return listeners.add(listener); + } + + @Override + public boolean removeListener(final ClientSessionListener listener) { + return listeners.remove(listener); + } + + @Override + public Optional resolve(final String clientId) { + return Optional.ofNullable(clientSessions.get(clientId)); + } + +} diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/jsonrpc/DefaultGLSPServer.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/jsonrpc/DefaultGLSPServer.java index ee64c992..54ad6ef6 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/jsonrpc/DefaultGLSPServer.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/jsonrpc/DefaultGLSPServer.java @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2019 EclipseSource and others. + * Copyright (c) 2019-2020 EclipseSource and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -20,35 +20,38 @@ import java.util.concurrent.CompletableFuture; import org.apache.log4j.Logger; -import org.eclipse.glsp.api.action.ActionMessage; import org.eclipse.glsp.api.action.ActionDispatcher; -import org.eclipse.glsp.api.jsonrpc.GLSPClient; -import org.eclipse.glsp.api.jsonrpc.GLSPClientProvider; -import org.eclipse.glsp.api.jsonrpc.GLSPServer; -import org.eclipse.glsp.api.jsonrpc.InitializeParameters; +import org.eclipse.glsp.api.action.ActionMessage; +import org.eclipse.glsp.api.action.kind.RequestModelAction; +import org.eclipse.glsp.api.jsonrpc.GLSPJsonrpcClient; +import org.eclipse.glsp.api.jsonrpc.GLSPJsonrpcServer; import org.eclipse.glsp.api.model.ModelStateProvider; -import org.eclipse.glsp.api.types.ServerStatus; -import org.eclipse.glsp.api.types.Severity; +import org.eclipse.glsp.api.protocol.ClientSessionManager; +import org.eclipse.glsp.api.protocol.GLSPClient; +import org.eclipse.glsp.api.protocol.GLSPServerException; +import org.eclipse.glsp.api.protocol.InitializeParameters; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.inject.Inject; -public class DefaultGLSPServer implements GLSPServer { +public class DefaultGLSPServer implements GLSPJsonrpcServer { + private static Logger log = Logger.getLogger(DefaultGLSPServer.class); @Inject protected ModelStateProvider modelStateProvider; @Inject - protected GLSPClientProvider clientProxyProvider; + protected ClientSessionManager sessionManager; + @Inject protected ActionDispatcher actionDispatcher; - private static Logger log = Logger.getLogger(DefaultGLSPServer.class); - - private ServerStatus status; private GLSPClient clientProxy; - private Class optionsClazz; + private final Class optionsClazz; + private boolean initialized; + + private String applicationId; public DefaultGLSPServer() { this(null); @@ -62,25 +65,33 @@ public DefaultGLSPServer(final Class optionsClazz) { @SuppressWarnings("checkstyle:IllegalCatch") public CompletableFuture initialize(final InitializeParameters params) { try { + boolean completed; + this.applicationId = params.getApplicationId(); if (optionsClazz != null && params.getOptions() instanceof JsonElement) { T options = new Gson().fromJson((JsonElement) params.getOptions(), optionsClazz); - return handleOptions(options); + completed = handleOptions(options); + } else { + completed = handleOptions(null); } - return handleOptions(null); + this.initialized = completed; + return CompletableFuture.completedFuture(completed); } catch (Throwable ex) { log.error("Could not initialize server due to corrupted options: " + params.getOptions(), ex); + this.initialized = false; return CompletableFuture.completedFuture(false); } } - protected CompletableFuture handleOptions(final T options) { - return CompletableFuture.completedFuture(true); + protected boolean handleOptions(final T options) { + return true; } @Override - public void connect(final GLSPClient clientProxy) { + public void connect(final GLSPJsonrpcClient clientProxy) { this.clientProxy = clientProxy; - status = new ServerStatus(Severity.OK, "Connection successfull"); + if (clientProxy != null) { + this.sessionManager.connectClient(clientProxy); + } } @Override @@ -89,10 +100,18 @@ public void process(final ActionMessage message) { log.debug("process " + message); String clientId = message.getClientId(); try { - // FIXME: It seems we don't get access to the clientId when the connection - // is initialized. ClientId is only retrieved through messages; so this - // is currently the earliest we can register the clientProxy - this.clientProxyProvider.register(clientId, clientProxy); + if (message.getAction() instanceof RequestModelAction) { + if (!this.sessionManager.createClientSession(clientProxy, clientId)) { + throw new GLSPServerException(String.format( + "Could not create session for client id '%s'. Another session with the same id already exists", + clientId)); + } + } + + if (!initialized) { + throw new GLSPServerException( + String.format("Could not process action message '%s'. The server has not been initalized yet", message)); + } actionDispatcher.dispatch(message); } catch (RuntimeException e) { String errorMsg = "Could not process message:" + message; @@ -102,16 +121,15 @@ public void process(final ActionMessage message) { } @Override - public ServerStatus getStatus() { return status; } - - @Override - public CompletableFuture shutdown() { - return new CompletableFuture<>(); + public CompletableFuture shutdown() { + boolean completed = false; + if (this.clientProxy != null) { + this.initialized = false; + completed = sessionManager.disconnectClient(this.clientProxy); + this.clientProxy = null; + } + return CompletableFuture.completedFuture(completed); } - @Override - public void exit(final String clientId) { - modelStateProvider.remove(clientId); - clientProxyProvider.remove(clientId); - } + public String getApplicationId() { return applicationId; } } diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/DefaultGLSPServerLauncher.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/DefaultGLSPServerLauncher.java index 64988339..b9e5628d 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/DefaultGLSPServerLauncher.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/DefaultGLSPServerLauncher.java @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2019 EclipseSource and others. + * Copyright (c) 2019-2020 EclipseSource and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -32,10 +32,11 @@ import java.util.function.Function; import org.apache.log4j.Logger; -import org.eclipse.glsp.api.di.GLSPModule; -import org.eclipse.glsp.api.json.GsonConfigurator; -import org.eclipse.glsp.api.jsonrpc.GLSPClient; -import org.eclipse.glsp.api.jsonrpc.GLSPServer; +import org.eclipse.glsp.api.jsonrpc.GLSPJsonrpcClient; +import org.eclipse.glsp.api.jsonrpc.GLSPJsonrpcServer; +import org.eclipse.glsp.api.protocol.GLSPServer; +import org.eclipse.glsp.server.di.GLSPModule; +import org.eclipse.glsp.server.json.GsonConfigurator; import org.eclipse.lsp4j.jsonrpc.Launcher; import org.eclipse.lsp4j.jsonrpc.MessageConsumer; @@ -100,14 +101,14 @@ private void createClientConnection(final AsynchronousSocketChannel socketChanne Consumer configureGson = (final GsonBuilder builder) -> gsonConf.configureGsonBuilder(builder); Function wrapper = Function.identity(); - GLSPServer languageServer = injector.getInstance(GLSPServer.class); - - Launcher launcher = Launcher.createIoLauncher(languageServer, GLSPClient.class, in, out, + GLSPJsonrpcServer glspServer = (GLSPJsonrpcServer) injector.getInstance(GLSPServer.class); + Launcher launcher = Launcher.createIoLauncher(glspServer, GLSPJsonrpcClient.class, in, out, threadPool, wrapper, configureGson); - languageServer.connect(launcher.getRemoteProxy()); + glspServer.connect(launcher.getRemoteProxy()); log.info("Starting GLSP server connection for client " + socketChannel.getRemoteAddress()); launcher.startListening().get(); log.info("Stopping GLSP server connection for client" + socketChannel.getRemoteAddress()); + glspServer.shutdown(); } catch (IOException | InterruptedException | ExecutionException ex) { log.error("Failed to create client connection " + ex.getMessage(), ex); } finally { diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/GLSPServerLauncher.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/GLSPServerLauncher.java index b7b5e628..e9de83bd 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/GLSPServerLauncher.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/GLSPServerLauncher.java @@ -19,7 +19,7 @@ import java.util.Arrays; import java.util.List; -import org.eclipse.glsp.api.di.GLSPModule; +import org.eclipse.glsp.server.di.GLSPModule; import com.google.inject.Guice; import com.google.inject.Injector; @@ -51,4 +51,5 @@ public Injector createInjector() { public abstract void shutdown(); public GLSPModule getGLSPModule() { return glspModule; } + } diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/model/DefaultModelStateProvider.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/model/DefaultModelStateProvider.java index 87c73cf5..af73068b 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/model/DefaultModelStateProvider.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/model/DefaultModelStateProvider.java @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2019 EclipseSource and others. + * Copyright (c) 2019-2020 EclipseSource and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -21,18 +21,30 @@ import org.eclipse.glsp.api.model.GraphicalModelState; import org.eclipse.glsp.api.model.ModelStateProvider; +import org.eclipse.glsp.api.protocol.ClientSessionListener; +import org.eclipse.glsp.api.protocol.ClientSessionManager; +import org.eclipse.glsp.api.protocol.GLSPClient; +import com.google.inject.Inject; import com.google.inject.Singleton; @Singleton -public class DefaultModelStateProvider implements ModelStateProvider { +public class DefaultModelStateProvider implements ModelStateProvider, ClientSessionListener { + @Inject() + protected ClientSessionManager sessionManager; private final Map clientModelStates; + @Inject() public DefaultModelStateProvider() { clientModelStates = new ConcurrentHashMap<>(); } + @Inject() + public void postConstruct() { + sessionManager.addListener(this); + } + @Override public Optional getModelState(final String clientId) { return Optional.ofNullable(clientModelStates.get(clientId)); @@ -55,4 +67,8 @@ public void remove(final String clientId) { clientModelStates.remove(clientId); } + @Override + public void sessionClosed(final String clientId, final GLSPClient client) { + this.clientModelStates.remove(clientId); + } } diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/model/JsonFileModelFactory.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/model/JsonFileModelFactory.java index 9a8603f3..2e8ed26a 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/model/JsonFileModelFactory.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/model/JsonFileModelFactory.java @@ -25,8 +25,8 @@ import org.eclipse.glsp.api.action.kind.RequestModelAction; import org.eclipse.glsp.api.factory.GraphGsonConfiguratorFactory; import org.eclipse.glsp.api.factory.ModelFactory; -import org.eclipse.glsp.api.jsonrpc.GLSPServerException; import org.eclipse.glsp.api.model.GraphicalModelState; +import org.eclipse.glsp.api.protocol.GLSPServerException; import org.eclipse.glsp.api.utils.ClientOptions; import org.eclipse.glsp.graph.GGraph; import org.eclipse.glsp.graph.GModelRoot; diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operationhandler/ChangeBoundsOperationHandler.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operationhandler/ChangeBoundsOperationHandler.java index 0542670b..c991b406 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operationhandler/ChangeBoundsOperationHandler.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operationhandler/ChangeBoundsOperationHandler.java @@ -15,7 +15,7 @@ ********************************************************************************/ package org.eclipse.glsp.server.operationhandler; -import static org.eclipse.glsp.api.jsonrpc.GLSPServerException.getOrThrow; +import static org.eclipse.glsp.api.protocol.GLSPServerException.getOrThrow; import org.apache.log4j.Logger; import org.eclipse.glsp.api.model.GraphicalModelState; diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operationhandler/ChangeRoutingPointsHandler.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operationhandler/ChangeRoutingPointsHandler.java index a9df6cef..49901f71 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operationhandler/ChangeRoutingPointsHandler.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operationhandler/ChangeRoutingPointsHandler.java @@ -15,7 +15,7 @@ ********************************************************************************/ package org.eclipse.glsp.server.operationhandler; -import static org.eclipse.glsp.api.jsonrpc.GLSPServerException.getOrThrow; +import static org.eclipse.glsp.api.protocol.GLSPServerException.getOrThrow; import org.eclipse.emf.common.util.EList; import org.eclipse.glsp.api.model.GraphicalModelState; diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operationhandler/ReconnectOperationHandler.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operationhandler/ReconnectOperationHandler.java index 23d739ac..22357ed3 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operationhandler/ReconnectOperationHandler.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operationhandler/ReconnectOperationHandler.java @@ -15,7 +15,7 @@ ********************************************************************************/ package org.eclipse.glsp.server.operationhandler; -import static org.eclipse.glsp.api.jsonrpc.GLSPServerException.getOrThrow; +import static org.eclipse.glsp.api.protocol.GLSPServerException.getOrThrow; import static org.eclipse.glsp.server.utils.GModelUtil.IS_CONNECTABLE; import org.eclipse.glsp.api.model.GraphicalModelState;