
com.apollographql.java.client.network.ws.protocol.WsProtocol Maven / Gradle / Ivy
package com.apollographql.java.client.network.ws.protocol;
import com.apollographql.apollo.api.Adapters;
import com.apollographql.apollo.api.ApolloRequest;
import com.apollographql.apollo.api.CustomScalarAdapters;
import com.apollographql.apollo.api.Operation;
import com.apollographql.apollo.api.json.BufferedSinkJsonWriter;
import com.apollographql.apollo.api.json.BufferedSourceJsonReader;
import com.apollographql.java.client.network.ws.WebSocketConnection;
import okio.Buffer;
import okio.ByteString;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.Map;
public abstract class WsProtocol {
protected WebSocketConnection webSocketConnection;
protected Listener listener;
public WsProtocol(WebSocketConnection webSocketConnection, Listener listener) {
this.webSocketConnection = webSocketConnection;
this.listener = listener;
}
public abstract void connectionInit();
public abstract void handleServerMessage(Map messageMap);
public abstract void startOperation(ApolloRequest request);
public abstract void stopOperation(ApolloRequest request);
protected void sendMessageMap(Map messageMap, WsFrameType frameType) {
switch (frameType) {
case Text:
sendMessageMapText(messageMap);
break;
case Binary:
sendMessageMapBinary(messageMap);
break;
}
}
protected void sendMessageMapText(Map messageMap) {
webSocketConnection.send(toJsonString(messageMap));
}
protected void sendMessageMapBinary(Map messageMap) {
webSocketConnection.send(toJsonByteString(messageMap));
}
/**
* Receive a new WebMessage message as a `Map`. Messages that aren't Json objects are ignored and the method will block
* until the next message. Returns null if the connection is closed.
*
* @param timeoutMs the timeout in milliseconds or -1 for no timeout
*/
@Nullable
protected Map receiveMessageMap(long timeoutMs) {
while (true) {
String messageJson = webSocketConnection.receive(timeoutMs);
if (messageJson == null) {
return null;
}
Map map = toMessageMap(messageJson);
if (map != null) {
return map;
}
}
}
public void run() {
while (true) {
Map messageMap = receiveMessageMap(-1L);
if (messageMap == null) {
// Connection closed
listener.networkError(new IOException("Connection closed"));
return;
}
handleServerMessage(messageMap);
}
}
protected static String toJsonString(Map messageMap) {
Buffer buffer = new Buffer();
BufferedSinkJsonWriter writer = new BufferedSinkJsonWriter(buffer);
try {
Adapters.AnyAdapter.toJson(writer, CustomScalarAdapters.Empty, messageMap);
} catch (IOException ignored) {
}
return buffer.readUtf8();
}
protected static ByteString toJsonByteString(Map messageMap) {
Buffer buffer = new Buffer();
BufferedSinkJsonWriter writer = new BufferedSinkJsonWriter(buffer);
try {
Adapters.AnyAdapter.toJson(writer, CustomScalarAdapters.Empty, messageMap);
} catch (IOException ignored) {
}
return buffer.readByteString();
}
private static Map toMessageMap(String messageJson) {
try {
//noinspection unchecked
return (Map) Adapters.AnyAdapter.fromJson(new BufferedSourceJsonReader(new Buffer().writeUtf8(messageJson)), CustomScalarAdapters.Empty);
} catch (Exception e) {
return null;
}
}
public void close() {
webSocketConnection.close();
}
public interface Listener {
/**
* A response was received. payload might contain "errors". For subscriptions, several responses might be received.
*/
void operationResponse(String id, Map payload);
/**
* An error was received in relation to an operation
*/
void operationError(String id, Map payload);
/**
* An operation is complete
*/
void operationComplete(String id);
/**
* A general error was received. A general error is a protocol error that doesn't have an operation id. If you have an operation id, use
* `operationError` instead.
*/
void generalError(Map payload);
/**
* A network error occurred A network error is terminal
*/
void networkError(Throwable cause);
}
public enum WsFrameType {
Text,
Binary
}
public interface Factory {
String getName();
WsProtocol create(WebSocketConnection webSocketConnection, Listener listener);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy