org.apache.openmeetings.core.util.WebSocketHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.openmeetings.core.util.WebSocketHelper.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License") +  you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.openmeetings.core.util;

import static org.apache.openmeetings.util.OpenmeetingsVariables.getWicketApplicationName;

import java.io.IOException;
import java.util.Collection;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

import org.apache.openmeetings.IApplication;
import org.apache.openmeetings.core.util.ws.WsMessageAll;
import org.apache.openmeetings.core.util.ws.WsMessageRoom;
import org.apache.openmeetings.core.util.ws.WsMessageRoomMsg;
import org.apache.openmeetings.core.util.ws.WsMessageRoomOthers;
import org.apache.openmeetings.core.util.ws.WsMessageUser;
import org.apache.openmeetings.db.entity.basic.Client;
import org.apache.openmeetings.db.entity.basic.IWsClient;
import org.apache.openmeetings.db.manager.IClientManager;
import org.apache.openmeetings.db.util.ws.RoomMessage;
import org.apache.openmeetings.db.util.ws.TextRoomMessage;
import org.apache.openmeetings.util.NullStringer;
import org.apache.openmeetings.util.ws.IClusterWsMessage;
import org.apache.wicket.Application;
import org.apache.wicket.protocol.ws.WebSocketSettings;
import org.apache.wicket.protocol.ws.api.IWebSocketConnection;
import org.apache.wicket.protocol.ws.api.registry.IWebSocketConnectionRegistry;
import org.apache.wicket.protocol.ws.api.registry.PageIdKey;
import org.apache.wicket.protocol.ws.concurrent.Executor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.openjson.JSONObject;

public class WebSocketHelper {
    private static final Logger log = LoggerFactory.getLogger(WebSocketHelper.class);

    public static void sendClient(final IWsClient inC, byte[] b) {
        if (inC != null) {
            sendClient(inC, c -> {
                try {
                    c.sendMessage(b, 0, b.length);
                } catch (IOException e) {
                    log.error("Error while sending binary message to client", e);
                }
            });
        }
    }

    public static void sendClient(final IWsClient inC, JSONObject msg) {
        log.trace("Sending WebSocket message to Client: {} -> {}", inC, msg);
        if (inC != null) {
            sendClient(inC, c -> {
                try {
                    c.sendMessage(msg.toString());
                } catch (IOException e) {
                    log.error("Error while sending message to client", e);
                }
            });
        }
    }

    public static IApplication getApp() {
        return (IApplication) Application.get(getWicketApplicationName());
    }

    private static void sendClient(IWsClient client, Consumer<IWebSocketConnection> wsc) {
        Application app = (Application) getApp();
        WebSocketSettings settings = WebSocketSettings.Holder.get(app);
        IWebSocketConnectionRegistry reg = settings.getConnectionRegistry();
        Executor executor = settings.getWebSocketPushMessageExecutor();
        final IWebSocketConnection wc = reg.getConnection(app, client.getSessionId(),
                new PageIdKey(client.getPageId()));
        if (wc != null && wc.isOpen()) {
            executor.run(() -> wsc.accept(wc));
        }
    }

    public static void send(IClusterWsMessage msg) {
        if (msg instanceof WsMessageRoomMsg) {
            sendRoom(((WsMessageRoomMsg) msg).getMsg(), false);
        } else if (msg instanceof WsMessageRoomOthers) {
            WsMessageRoomOthers m = (WsMessageRoomOthers) msg;
            sendRoomOthers(m.getRoomId(), m.getUid(), m.getMsg(), false);
        } else if (msg instanceof WsMessageRoom) {
            WsMessageRoom m = (WsMessageRoom) msg;
            sendRoom(m.getRoomId(), m.getMsg(), false);
        } else if (msg instanceof WsMessageUser) {
            WsMessageUser m = (WsMessageUser) msg;
            sendUser(m.getUserId(), m.getMsg(), null, false);
        } else if (msg instanceof WsMessageAll) {
            sendAll(((WsMessageAll) msg).getMsg(), false);
        }
    }

    public static void sendRoom(final RoomMessage m) {
        sendRoom(m, true);
    }

    private static void sendRoom(final RoomMessage m, boolean publish) {
        if (publish) {
            publish(new WsMessageRoomMsg(m));
        }
        log.debug("Sending WebSocket message to room: {} {}", m.getType(),
                m instanceof TextRoomMessage ? ((TextRoomMessage) m).getText() : "");
        sendRoom(m.getRoomId(), (t, c) -> t.sendMessage(m), null);
    }

    public static void sendServer(final RoomMessage m) {
        log.debug("Sending WebSocket message to All: {}", m);
        sendAll(c -> {
            try {
                c.sendMessage(m);
            } catch (Exception e) {
                log.error("Error while sending message to Server", e);
            }
        });
    }

    public static void sendRoom(final Long roomId, final JSONObject m) {
        sendRoom(roomId, m, true);
    }

    private static void sendRoom(final Long roomId, final JSONObject m, boolean publish) {
        if (publish) {
            publish(new WsMessageRoom(roomId, m));
        }
        sendRoom(roomId, m, null, null);
    }

    public static void sendRoomOthers(final Long roomId, final String uid, final JSONObject m) {
        sendRoomOthers(roomId, uid, m, true);
    }

    private static void sendRoomOthers(final Long roomId, final String uid, final JSONObject m, boolean publish) {
        if (publish) {
            publish(new WsMessageRoomOthers(roomId, uid, m));
        }
        sendRoom(roomId, m, c -> !uid.equals(c.getUid()), null);
    }

    public static void sendUser(final Long userId, final JSONObject m) {
        sendUser(userId, m, null, true);
    }

    static void sendUser(final Long userId, final JSONObject m, BiFunction<JSONObject, Client, JSONObject> func,
            boolean publish) {
        if (publish) {
            publish(new WsMessageUser(userId, m));
        }
        send(a -> ((IApplication) a).getBean(IClientManager.class).listByUser(userId),
                (t, c) -> doSend(t, c, m, func, "user"), null);
    }

    public static void sendAll(final String m) {
        sendAll(m, true);
    }

    private static void sendAll(final String m, boolean publish) {
        if (publish) {
            publish(new WsMessageAll(m));
        }
        log.debug("Sending text WebSocket message to All: {}", m);
        sendAll(c -> doSend(c, m, "ALL"));
    }

    private static void sendAll(Consumer<IWebSocketConnection> sender) {
        new Thread(() -> {
            Application app = (Application) getApp();
            if (app == null) {
                return; // Application is not ready
            }
            WebSocketSettings settings = WebSocketSettings.Holder.get(app);
            IWebSocketConnectionRegistry reg = settings.getConnectionRegistry();
            Executor executor = settings.getWebSocketPushMessageExecutor();
            for (IWebSocketConnection c : reg.getConnections(app)) {
                executor.run(() -> sender.accept(c));
            }
        }).start();
    }

    protected static void publish(IClusterWsMessage m) {
        IApplication app = getApp();
        new Thread(() -> app.publishWsTopic(m)).start();
    }

    protected static void sendRoom(final Long roomId, final JSONObject m, Predicate<Client> check,
            BiFunction<JSONObject, Client, JSONObject> func) {
        log.debug("Sending json WebSocket message to room: {}", m);
        sendRoom(roomId, (t, c) -> doSend(t, c, m, func, "room"), check);
    }

    static void doSend(IWebSocketConnection conn, Client c, JSONObject msg,
            BiFunction<JSONObject, Client, JSONObject> func, String suffix) {
        doSend(conn, (func == null ? msg : func.apply(msg, c)).toString(new NullStringer()), suffix);
    }

    private static void doSend(IWebSocketConnection c, String msg, String suffix) {
        try {
            c.sendMessage(msg);
        } catch (IOException e) {
            log.error("Error while sending message to {}", suffix, e);
        }
    }

    private static void sendRoom(final Long roomId, BiConsumer<IWebSocketConnection, Client> consumer,
            Predicate<Client> check) {
        send(a -> ((IApplication) a).getBean(IClientManager.class).listByRoom(roomId), consumer, check);
    }

    static void send(final Function<Application, Collection<Client>> func,
            BiConsumer<IWebSocketConnection, Client> consumer, Predicate<Client> check) {
        new Thread(() -> {
            Application app = (Application) getApp();
            if (app == null) {
                return; // Application is not ready
            }
            WebSocketSettings settings = WebSocketSettings.Holder.get(app);
            IWebSocketConnectionRegistry reg = settings.getConnectionRegistry();
            Executor executor = settings.getWebSocketPushMessageExecutor();
            for (Client c : func.apply(app)) {
                if (check == null || check.test(c)) {
                    final IWebSocketConnection wc = reg.getConnection(app, c.getSessionId(),
                            new PageIdKey(c.getPageId()));
                    if (wc != null && wc.isOpen()) {
                        executor.run(() -> consumer.accept(wc, c));
                    }
                }
            }
        }).start();
    }
}