
com.github.gkutiel.flip.web.Remote Maven / Gradle / Ivy
package com.github.gkutiel.flip.web;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.websocket.WebSocket;
import org.eclipse.jetty.websocket.WebSocketServlet;
import ch.lambdaj.Lambda;
import com.github.gkutiel.flip.AFlip;
import com.github.gkutiel.flip.AFlip.Hook;
import com.github.gkutiel.flip.utils.Utils;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.gson.Gson;
public class Remote extends ServletHolder {
public interface Guard {
boolean accept(Req req, String key);
}
@SuppressWarnings("unused")
private static class Cb {
final String name;
final Object[] args;
public Cb(final String name, final Object[] args) {
this.name = name;
this.args = args;
}
}
private class FlipSocket implements WebSocket {
private T remote;
private Connection con;
private String key;
@SuppressWarnings("unchecked")
public FlipSocket(final String key) {
this.key = key;
remote = (T) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class>[] { c }, new InvocationHandler() {
@Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
if (method.getDeclaringClass().equals(c)) {
con.sendMessage(GSON.toJson(new Cb(method.getName(), args)));
return null;
}
return method.invoke(FlipSocket.this, args);
}
});
}
@Override
public void onClose(final int closeCode, final String message) {
remotes.remove(key, remote);
}
@Override
public void onOpen(final Connection con) {
this.con = con;
remotes.put(key, remote);
}
}
private static final String _JS = Utils.Resource.load("_.js");
static {
AFlip.hook(new Hook() {
@Override
public void hook(final AFlip flip) {
flip.add(new ServletHolder(new HttpServlet() {
@Override
protected void doGet(final HttpServletRequest req, final HttpServletResponse res) throws ServletException, IOException {
final ServletOutputStream out = res.getOutputStream();
out.print(_JS);
out.close();
}
}), "/_.js");
}
});
}
private static final Gson GSON = new Gson();
private final Multimap remotes = HashMultimap.create();
private Class c;
private static final Guard KIND_GUARD = new Guard() {
@Override
public boolean accept(final Req req, final String key) {
return true;
}
};
public Remote(final Class c) {
this(c, KIND_GUARD);
}
public Remote(final Class c, final Guard guard) {
this.c = c;
setServlet(new WebSocketServlet() {
@Override
public WebSocket doWebSocketConnect(final HttpServletRequest req, final String key) {
if (guard.accept(HttpUtils.req(req), key)) return new FlipSocket(key);
return null;
}
});
}
public T select(final String key) {
return Lambda.forEach(remotes.get(key));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy