diff options
Diffstat (limited to 'language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java')
-rw-r--r-- | language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java b/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java new file mode 100644 index 00000000..25f67545 --- /dev/null +++ b/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java | |||
@@ -0,0 +1,94 @@ | |||
1 | package tools.refinery.language.web.xtext.servlet; | ||
2 | |||
3 | import java.io.IOException; | ||
4 | import java.io.Reader; | ||
5 | |||
6 | import org.eclipse.jetty.websocket.api.Session; | ||
7 | import org.eclipse.jetty.websocket.api.StatusCode; | ||
8 | import org.eclipse.jetty.websocket.api.WriteCallback; | ||
9 | import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose; | ||
10 | import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect; | ||
11 | import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError; | ||
12 | import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; | ||
13 | import org.eclipse.jetty.websocket.api.annotations.WebSocket; | ||
14 | import org.eclipse.xtext.resource.IResourceServiceProvider; | ||
15 | import org.eclipse.xtext.web.server.ISession; | ||
16 | import org.slf4j.Logger; | ||
17 | import org.slf4j.LoggerFactory; | ||
18 | |||
19 | import com.google.gson.Gson; | ||
20 | import com.google.gson.JsonIOException; | ||
21 | import com.google.gson.JsonParseException; | ||
22 | |||
23 | @WebSocket | ||
24 | public class XtextWebSocket { | ||
25 | private static final Logger LOG = LoggerFactory.getLogger(XtextWebSocket.class); | ||
26 | |||
27 | private final Gson gson = new Gson(); | ||
28 | |||
29 | private final TransactionExecutor executor; | ||
30 | |||
31 | public XtextWebSocket(TransactionExecutor executor) { | ||
32 | this.executor = executor; | ||
33 | } | ||
34 | |||
35 | public XtextWebSocket(ISession session, IResourceServiceProvider.Registry resourceServiceProviderRegistry) { | ||
36 | this(new TransactionExecutor(session, resourceServiceProviderRegistry)); | ||
37 | } | ||
38 | |||
39 | @OnWebSocketConnect | ||
40 | public void onConnect(Session webSocketSession) { | ||
41 | LOG.debug("New websocket connection from {}", webSocketSession.getRemoteAddress()); | ||
42 | } | ||
43 | |||
44 | @OnWebSocketClose | ||
45 | public void onClose(Session webSocketSession, int statusCode, String reason) { | ||
46 | if (statusCode == StatusCode.NORMAL) { | ||
47 | LOG.debug("{} closed connection normally: {}", webSocketSession.getRemoteAddress(), reason); | ||
48 | } else { | ||
49 | LOG.warn("{} closed connection with status code {}: {}", webSocketSession.getRemoteAddress(), statusCode, | ||
50 | reason); | ||
51 | } | ||
52 | } | ||
53 | |||
54 | @OnWebSocketError | ||
55 | public void onError(Session webSocketSession, Throwable error) { | ||
56 | LOG.error("Internal websocket error in connection from" + webSocketSession.getRemoteAddress(), error); | ||
57 | } | ||
58 | |||
59 | @OnWebSocketMessage | ||
60 | public void onMessage(Session webSocketSession, Reader reader) { | ||
61 | XtextWebSocketRequest request; | ||
62 | try { | ||
63 | request = gson.fromJson(reader, XtextWebSocketRequest.class); | ||
64 | } catch (JsonIOException e) { | ||
65 | LOG.error("Cannot read from websocket from" + webSocketSession.getRemoteAddress(), e); | ||
66 | if (webSocketSession.isOpen()) { | ||
67 | webSocketSession.close(StatusCode.SERVER_ERROR, "Cannot read payload"); | ||
68 | } | ||
69 | return; | ||
70 | } catch (JsonParseException e) { | ||
71 | LOG.warn("Malformed websocket request from" + webSocketSession.getRemoteAddress(), e); | ||
72 | webSocketSession.close(XtextStatusCode.INVALID_JSON, "Invalid JSON payload"); | ||
73 | return; | ||
74 | } | ||
75 | try { | ||
76 | executor.handleRequest(request, response -> sendResponse(webSocketSession, response)); | ||
77 | } catch (IOException e) { | ||
78 | LOG.warn("Cannot initiaite async write to websocket " + webSocketSession.getRemoteAddress(), e); | ||
79 | if (webSocketSession.isOpen()) { | ||
80 | webSocketSession.close(StatusCode.SERVER_ERROR, "Cannot write payload"); | ||
81 | } | ||
82 | } | ||
83 | } | ||
84 | |||
85 | protected void sendResponse(Session webSocketSession, XtextWebSocketResponse response) throws IOException { | ||
86 | var responseString = gson.toJson(response); | ||
87 | webSocketSession.getRemote().sendPartialString(responseString, true, new WriteCallback() { | ||
88 | @Override | ||
89 | public void writeFailed(Throwable x) { | ||
90 | LOG.warn("Cannot complete async write to websocket " + webSocketSession.getRemoteAddress(), x); | ||
91 | } | ||
92 | }); | ||
93 | } | ||
94 | } | ||