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

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