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

com.yy.androidlib.websocket.StompClient Maven / Gradle / Ivy

The newest version!
package com.yy.androidlib.websocket;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.google.gson.*;

import java.lang.reflect.Type;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

public class StompClient implements WebSocketClient.Listener {

    private Config config;
    private Set callbacks = new HashSet();
    private Map replayCallbacks = new HashMap();
    private Map subscribeCallbacks = new HashMap();
    private final AtomicInteger subscriptionIndex = new AtomicInteger();
    private Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new JsonDeserializer() {

        @Override
        public Object deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            return json == null ? null : new Date(json.getAsLong());
        }
    }).registerTypeAdapter(Date.class, new JsonSerializer() {
        @Override
        public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
            return src == null ? new JsonPrimitive(0l) : new JsonPrimitive(src.getTime());
        }
    }).create();

    private AntPathMatcher matcher = new AntPathMatcher();
    private int requestId;
    private static final String TAG = "Stomp";
    private Handler handler = new Handler(Looper.getMainLooper());
    private WebSocketClient webSocket;
    private String url;

    /*
        connecttask
     */
    private Runnable connectTask = new Runnable() {
        @Override
        public void run() {
            if (webSocket == null) {
                Log.v(TAG, "auto reconnect, webSocket null or not open");
                try {
                    webSocket = new WebSocketClient(new URI(url), StompClient.this);
                } catch (URISyntaxException e) {
                    throw new IllegalArgumentException(e);
                }
            }
            if (!webSocket.isConnected()) {
                webSocket.connect();
            }
            handler.removeCallbacks(this);
            handler.postDelayed(this, 5000L);
        }
    };

    @Override
    public void onConnect() {
        Log.i(TAG, "onConnect");
        sendCommand(Command.CONNECT, null, "login", null);
    }

    @Override
    public void onMessage(String s) {
        final Message message = Message.parse(s);
        Log.d(TAG, "onStringAvailable \n" + message.getCommand() + "\nheader\n" + message.getHeaders() + "\nbody\n" + message.getBody());
        if (Command.CONNECTED.is(message.getCommand())) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    onConnectSuccess();
                }
            });
        } else if (Command.MESSAGE.is(message.getCommand())) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    onReceive(message.getDestination(), message);
                }
            });
        }
    }

    @Override
    public void onMessage(byte[] data) {

    }

    @Override
    public void onDisconnect(int code, String reason) {
        Log.i(TAG, "onDisconnect");
    }

    @Override
    public void onError(Exception error) {
        Log.e(TAG, "onError", error);
    }

    public static abstract class ReplyHandler {

        private Class clazz;
        private Type type;

        public ReplyHandler() {

        }

        public ReplyHandler(Class clazz) {
            this.clazz = clazz;
        }

        public ReplyHandler(Type type) {
            this.type = type;
        }

        public abstract void onSuccess(Destination destination, T result);

        public abstract void onError(int code, String message);

        private T handle(Gson gson, String body, Destination destination, int respCode, String msg, String serverDataParseErrorTips) {
            T json = null;
            try {

                if (respCode == 1) {
                    if (!StringUtils.isEmpty(body)) {
                        if (clazz != null) {
                            json = (T) gson.fromJson(body, clazz);
                        } else if (type != null) {
                            json = gson.fromJson(body, type);
                        } else {
                            json = (T) "success";
                        }
                    }
                    this.onSuccess(destination, json);
                } else {
                    this.onError(respCode, msg);
                }
            } catch (Exception exception) {
                Log.e(TAG, "parse json error!", exception);
                this.onError(-1, serverDataParseErrorTips);
            }
            return json;
        }
    }

    public static abstract class SubscribeHandler extends ReplyHandler {

        public SubscribeHandler(Class clazz) {
            super(clazz);
        }

        @Override
        public void onError(int code, String message) {

        }
    }


    public StompClient(String url, Config config) {
        this.url = url;
        this.config = config;
    }

    public void onConnectSuccess() {
        subscribe("/user/queue/reply");
        for (Callback callback : callbacks) {
            callback.onConnected();
        }
    }

    private boolean sendCommand(Command command, String text, String... headers) {
        String transmit = Message.toRawString(command, headers, text);
        Log.d(TAG, "sendCommand \n" + transmit);
        if (webSocket != null && webSocket.isConnected()) {
            webSocket.send(transmit);
            return true;
        } else {
            return false;
        }
    }

    private void sendCommand(Command command, String text) {
        sendCommand(command, text, null);
    }

    private void sendCommand(Command command) {
        sendCommand(command, null, null);
    }

    public void subscribe(String path) {
        sendCommand(Command.SUBSCRIBE, null, Headers.DESTINATION_HEADER, path, Headers.SUBSCRIPTION_ID_HEADER, "sub" + subscriptionIndex.incrementAndGet());
    }

    public boolean send(String path, String body, String... headers) {
        if (headers != null && headers.length > 0) {
            String[] newHeaders = new String[headers.length + 2];
            for (int i = 0; i < headers.length; i++) {
                newHeaders[i] = headers[i];
            }
            newHeaders[headers.length] = Headers.DESTINATION_HEADER;
            newHeaders[headers.length + 1] = path;
            return sendCommand(Command.SEND, body, newHeaders);
        } else {
            return sendCommand(Command.SEND, body, Headers.DESTINATION_HEADER, path);
        }
    }

    public void request(String destination, Object body, final ReplyHandler replyHandler) {
        final String key = String.valueOf(this.requestId++);
        String json = null;
        if (body != null) {
            if (body instanceof String) {
                json = body.toString();
            } else {
                json = gson.toJson(body);
            }
        }
        if (send(destination, json, "request-id", key)) {
            if (replyHandler != null) {
                replayCallbacks.put(key, replyHandler);
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        ReplyHandler handler = replayCallbacks.remove(key);
                        if (handler != null) {
                            handler.onError(-1, config.getServerReplyTimeOutTips());
                        }
                    }
                }, 10000);
            }
        } else {
            if (replyHandler != null) {
                replyHandler.onError(-1, config.getCannotConnectToServerTips());
            }
        }

    }

    public void connect() {
        handler.removeCallbacks(connectTask);
        handler.post(connectTask);
    }

    public void subscribe(String destination, ReplyHandler patchListHandler) {
        subscribe(destination);
        subscribeCallbacks.put(destination, patchListHandler);
    }

    public interface Callback {

        void onConnected();

    }

    public void addConnectionCallback(Callback callback) {
        callbacks.add(callback);
    }

    public void onReceive(String path, Message message) {
        Destination destination = new Destination(matcher, path);
        String requestId = message.getHeaders().get("request-id");
        String code = message.getHeaders().get("response-code");
        int respCode = -1;
        if (code != null) {
            try {
                respCode = Integer.parseInt(code);
            } catch (Exception e) {
                Log.e(TAG, "parse code error");
            }
        }

        String msg = message.getHeaders().get("response-message");
        if (msg == null) {
            msg = "";
        }

        JsonResult jsonResult = new JsonResult(gson, message.getBody());
        if (path.equals("/user/queue/reply")) {
            ReplyHandler handler = replayCallbacks.remove(requestId);
            if (handler != null) {
                handler.handle(gson, message.getBody(), destination, respCode, msg, config.getServerDataParseErrorTips());
            }
        } else {
            for (Map.Entry entry : subscribeCallbacks.entrySet()) {
                if (destination.matches(entry.getKey())) {
                    entry.getValue().handle(gson, message.getBody(), destination, respCode, msg, config.getServerDataParseErrorTips());
                }
            }
        }

    }

    public static void main(String[] args) {
        AntPathMatcher matcher1 = new AntPathMatcher();
        System.out.println(matcher1.match("/abc/{param1}", "/abc/def"));
        System.out.println(matcher1.extractUriTemplateVariables("/abc/{param1}", "/abc/def"));

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy