001package io.github.flowersinthesand.portal.testsuite;
002
003import io.github.flowersinthesand.portal.DefaultServer;
004import io.github.flowersinthesand.portal.Server;
005import io.github.flowersinthesand.portal.Socket;
006import io.github.flowersinthesand.portal.Socket.Reply;
007import io.github.flowersinthesand.wes.Action;
008import io.github.flowersinthesand.wes.VoidAction;
009import io.github.flowersinthesand.wes.atmosphere.AtmosphereBridge;
010
011import java.util.Timer;
012import java.util.TimerTask;
013
014import javax.servlet.ServletContextEvent;
015import javax.servlet.ServletContextListener;
016import javax.servlet.annotation.WebListener;
017
018/**
019 * Bootstrap to start the test suite server.
020 * <p>
021 * To start the server on http://localhost:8080/,
022 * <p>
023 * {@code $ mvn jetty:run-war}
024 * <p>
025 * Then connect to http://localhost:8080/test/ using any test suite client.
026 * Also, this web server serves up test suite client running on browser written
027 * in JavaScript that is used to develop portal.js. Open http://localhost:8080
028 * in your browser to run the test suite in same-origin.
029 * <p>
030 * To run the test suite in cross-origin, start another server on
031 * http://localhost:8090/,
032 * <p>
033 * {@code $ mvn jetty:run-war -Djetty.port=8090}
034 * <p>
035 * Then open http://localhost:8090 in your browser. Test suite on 8090 will
036 * connect to 8080, cross-origin.
037 * 
038 * @author Donghwan Kim
039 */
040@WebListener
041public class ServerBootstrap implements ServletContextListener {
042    
043    @Override
044    public void contextInitialized(ServletContextEvent event) {
045        // Create a portal server
046        Server server = new DefaultServer();
047        
048        // This action is equivalent to socket handler of server.js in the portal repo
049        // https://github.com/flowersinthesand/portal/blob/1.1.1/test/server.js#L593-L611
050        server.socketAction(new Action<Socket>() {
051            @Override
052            public void on(final Socket socket) {
053                socket.on("echo", new Action<Object>() {
054                    @Override
055                    public void on(Object data) {
056                        socket.send("echo", data);
057                    }
058                })
059                .on("disconnect", new VoidAction() {
060                    @Override
061                    public void on() {
062                        new Timer(true).schedule(new TimerTask() {
063                            @Override
064                            public void run() {
065                                socket.close();
066                            }
067                        }, 100);
068                    }
069                })
070                .on("reply-by-server", new Action<Reply<Boolean>>() {
071                    @Override
072                    public void on(Reply<Boolean> reply) {
073                        if (reply.data()) {
074                            reply.done(reply.data());
075                        } else {
076                            reply.fail(reply.data());
077                        }
078                    }
079                })
080                .on("reply-by-client", new VoidAction() {
081                    @Override
082                    public void on() {
083                        socket.send("reply-by-client", 1, new Action<String>() {
084                            @Override
085                            public void on(String type) {
086                                socket.send(type);
087                            }
088                        });
089                    }
090                });
091            }
092        });
093        
094        // Install portal server by specifying path and attaching its wes actions to wes bridge
095        new AtmosphereBridge(event.getServletContext(), "/test").httpAction(server.httpAction()).websocketAction(server.websocketAction());
096    }
097    
098    @Override
099    public void contextDestroyed(ServletContextEvent sce) {}
100
101}