All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.nukkit.plugin.js.feature.ws.WsClientBuilder Maven / Gradle / Ivy

There is a newer version: 1.20.40-r1
Show newest version
package cn.nukkit.plugin.js.feature.ws;

import cn.nukkit.plugin.js.JSConcurrentManager;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Value;
import org.graalvm.polyglot.proxy.ProxyArray;
import org.graalvm.polyglot.proxy.ProxyExecutable;
import org.graalvm.polyglot.proxy.ProxyObject;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.WebSocket;
import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.CompletionStage;

public class WsClientBuilder implements ProxyObject {
    protected final Context sourceContext;

    protected WebSocket.Builder webSocketBuilder = HttpClient.newHttpClient().newWebSocketBuilder();
    protected URI uri;

    protected Value onOpenHandler;
    protected Value onErrorHandler;
    protected Value onBinaryHandler;
    protected Value onCloseHandler;
    protected Value onPingHandler;
    protected Value onPongHandler;
    protected Value onTextHandler;

    public static List memberKeys = List.of("reset", "setURI", "onOpen", "onError", "onBinary", "onClose", "onPing", "onPong", "onText", "addHeader", "setTimeout", "buildAsync");

    public WsClientBuilder(Context sourceContext) {
        this.sourceContext = sourceContext;
    }

    @Override
    public Object getMember(String key) {
        return switch (key) {
            case "reset" -> (ProxyExecutable) arguments -> {
                uri = null;
                onOpenHandler = null;
                onErrorHandler = null;
                onBinaryHandler = null;
                onCloseHandler = null;
                onPingHandler = null;
                onPongHandler = null;
                onTextHandler = null;
                webSocketBuilder = HttpClient.newHttpClient().newWebSocketBuilder();
                return this;
            };
            case "setURI" -> (ProxyExecutable) arguments -> {
                uri = URI.create(arguments[0].asString());
                return this;
            };
            case "onOpen" -> (ProxyExecutable) arguments -> {
                onOpenHandler = arguments[0];
                return this;
            };
            case "onError" -> (ProxyExecutable) arguments -> {
                onErrorHandler = arguments[0];
                return this;
            };
            case "onBinary" -> (ProxyExecutable) arguments -> {
                onBinaryHandler = arguments[0];
                return this;
            };
            case "onClose" -> (ProxyExecutable) arguments -> {
                onCloseHandler = arguments[0];
                return this;
            };
            case "onPing" -> (ProxyExecutable) arguments -> {
                onPingHandler = arguments[0];
                return this;
            };
            case "onPong" -> (ProxyExecutable) arguments -> {
                onPongHandler = arguments[0];
                return this;
            };
            case "onText" -> (ProxyExecutable) arguments -> {
                onTextHandler = arguments[0];
                return this;
            };
            case "addHeader" -> (ProxyExecutable) arguments -> {
                webSocketBuilder.header(arguments[0].asString(), arguments[1].asString());
                return this;
            };
            case "setTimeout" -> (ProxyExecutable) arguments -> {
                webSocketBuilder.connectTimeout(Duration.ofMillis(arguments[0].asLong()));
                return this;
            };
            case "buildAsync" -> (ProxyExecutable) arguments -> JSConcurrentManager.wrapPromise(sourceContext, webSocketBuilder.buildAsync(uri,
                    new WebSocket.Listener() {
                        @Override
                        public void onOpen(WebSocket webSocket) {
                            if (onOpenHandler.canExecute()) {
                                var res = onOpenHandler.execute(webSocket);
                                if (res.isBoolean() && res.asBoolean()) {
                                    webSocket.request(1);
                                }
                            }
                        }

                        @Override
                        public CompletionStage onText(WebSocket webSocket, CharSequence data, boolean last) {
                            if (onTextHandler.canExecute()) {
                                synchronized (sourceContext) {
                                    var res = onTextHandler.execute(webSocket, data, last);
                                    if (res.isBoolean() && res.asBoolean()) {
                                        webSocket.request(1);
                                    }
                                }
                            }
                            return null;
                        }

                        @Override
                        public CompletionStage onBinary(WebSocket webSocket, ByteBuffer data, boolean last) {
                            if (onBinaryHandler.canExecute()) {
                                synchronized (sourceContext) {
                                    var res = onBinaryHandler.execute(webSocket, Value.asValue(data), last);
                                    if (res.isBoolean() && res.asBoolean()) {
                                        webSocket.request(1);
                                    }
                                }
                            }
                            return null;
                        }

                        @Override
                        public CompletionStage onPing(WebSocket webSocket, ByteBuffer message) {
                            if (onPingHandler.canExecute()) {
                                synchronized (sourceContext) {
                                    var res = onPingHandler.execute(webSocket, Value.asValue(message));
                                    if (res.isBoolean() && res.asBoolean()) {
                                        webSocket.request(1);
                                    }
                                }
                            }
                            return null;
                        }

                        @Override
                        public CompletionStage onPong(WebSocket webSocket, ByteBuffer message) {
                            if (onPongHandler.canExecute()) {
                                synchronized (sourceContext) {
                                    var res = onPongHandler.execute(webSocket, Value.asValue(message));
                                    if (res.isBoolean() && res.asBoolean()) {
                                        webSocket.request(1);
                                    }
                                }
                            }
                            return null;
                        }

                        @Override
                        public CompletionStage onClose(WebSocket webSocket, int statusCode, String reason) {
                            if (onCloseHandler.canExecute()) {
                                synchronized (sourceContext) {
                                    onCloseHandler.execute(webSocket, statusCode, reason);
                                }
                            }
                            return null;
                        }

                        @Override
                        public void onError(WebSocket webSocket, Throwable error) {
                            if (onErrorHandler.canExecute()) {
                                synchronized (sourceContext) {
                                    onErrorHandler.execute(webSocket, error);
                                }
                            }
                        }
                    }));
            default -> null;
        };
    }

    @Override
    public Object getMemberKeys() {
        //noinspection unchecked ,rawtypes
        return ProxyArray.fromList((List) memberKeys);
    }

    @Override
    public boolean hasMember(String key) {
        return memberKeys.contains(key);
    }

    @Override
    public void putMember(String key, Value value) {
        throw new UnsupportedOperationException();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy