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"));
}
}