org.atmosphere.ttrex.RaceAtmosphereHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.atmosphere.ttrex.RaceAtmosphereHandler.java

Source

/** 
 * @author Thomas Verbeke
 * Broadcast data to all clients.
 * Handle incoming request.
 * **/

/*
    
 * Copyright 2013 Jeanfrancois Arcand
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.atmosphere.ttrex;

//BUGS 
//TODO Disconnected form server even when auto reconnect happens

import static org.atmosphere.cpr.ApplicationConfig.PROPERTY_USE_STREAM;

import org.atmosphere.config.service.AtmosphereHandlerService;
import org.atmosphere.cpr.AtmosphereResource;
import org.atmosphere.cpr.AtmosphereResourceEvent;
import org.atmosphere.cpr.AtmosphereResponse;
import org.atmosphere.cpr.Broadcaster;
import org.atmosphere.cpr.MetaBroadcaster;
import org.atmosphere.handler.AbstractReflectorAtmosphereHandler;
import org.atmosphere.interceptor.AtmosphereResourceLifecycleInterceptor;
import org.atmosphere.interceptor.BroadcastOnPostAtmosphereInterceptor;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;

/**
 * Simple AtmosphereHandler that implement the logic to build a Chat application.
 *
 * @author Jeanfrancois Arcand
 */

@AtmosphereHandlerService(path = "/ttrex", interceptors = { AtmosphereResourceLifecycleInterceptor.class,
        BroadcastOnPostAtmosphereInterceptor.class })
public class RaceAtmosphereHandler extends AbstractReflectorAtmosphereHandler
        implements ServletContextAttributeListener {
    BlockingQueue<ArrayList> readQueue = new LinkedBlockingQueue<ArrayList>();
    private static BlockingQueue<ArrayList> writeQueue = new LinkedBlockingQueue<ArrayList>(); //had to make it static because onStateChange was making it's own version of queue.

    Broadcaster broadcaster;
    private static final Logger logger = LoggerFactory.getLogger(AbstractReflectorAtmosphereHandler.class);
    private boolean queueInit = false;
    private boolean queueWriteInit = false;

    //is going to be called when both writeQueue and queue have been initialized & added to context
    public void attributeAdded(ServletContextAttributeEvent event) {

        readQueue = (BlockingQueue<ArrayList>) event.getServletContext().getAttribute("readQueue");

        //take first element of writeQueue

        if (readQueue == null || queueInit == true) {
            //System.out.println("queue is null");
        } else {
            queueInit = true;

            Thread thread = new Thread(new Runnable() {
                public void run() {
                    ArrayList item;
                    try {
                        //while (!(item = queue.take()).equals(SHUTDOWN_REQ)) {
                        while (true) {
                            item = readQueue.take();
                            JSONObject obj = new JSONObject();
                            //String s = JSONValue.toJSONString(item);
                            obj.put("type", item.get(0));
                            obj.put("data", item);
                            obj.put("source", "server");
                            MetaBroadcaster.getDefault().broadcastTo("/ttrex", obj.toJSONString());
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            thread.start();

            ArrayList frame = new ArrayList();
            frame.add("init");
            writeQueue.add(frame);
            writeQueue.add(frame);
            event.getServletContext().setAttribute("writeQueue", writeQueue);
        }

        if (queueWriteInit == true || queueInit == false) {
            //System.out.println("writeQueue is null");
        } else {
            queueWriteInit = true;
        }
    }

    public void attributeRemoved(ServletContextAttributeEvent event) {
        System.out.println("attribute removed");
    }

    public void attributeReplaced(ServletContextAttributeEvent event) {
        System.out.println("attribute replaced");
    }

    public void onRequest(AtmosphereResource resource) throws IOException {
        //Object message = resource.getAtmosphereResourceEvent().getMessage(); //is empty why?
        //leave connection open
        resource.suspend();

        BufferedReader reader = resource.getRequest().getReader();
        Object message = reader.readLine();

        if (message != null) {
            Object obj = JSONValue.parse(message.toString());
            JSONObject jsonObject = (JSONObject) obj;
            Object source = jsonObject.get("source");

            System.out.println("**onRequest: " + message.toString());
            ArrayList frame = new ArrayList();
            frame.add(jsonObject.get("type"));
            frame.add(jsonObject.get("data"));
            writeQueue.add(frame);
        }
    }

    public void destroy() {
        System.out.println("destroy");
    }

    public void onStateChange(AtmosphereResourceEvent event) throws IOException {

        /** This method gets invoked when: 
        (1) The remote connection gets closed, either by a browser or a proxy
        (2) The remote connection reach its maximum idle time (AtmosphereResource.suspend))
        (3) Everytime a broadcast operation is executed (broadcaster.broadcast)
        **/

        Object message = event.getMessage();

        AtmosphereResponse r = event.getResource().getResponse();
        if (message == null || event.isCancelled() || event.getResource().getRequest().destroyed())
            return;
        //message from server: broadcast

        Object obj = JSONValue.parse(message.toString());
        JSONObject jsonObject = (JSONObject) obj;
        Object source = jsonObject.get("source");

        if (event.getResource().getSerializer() != null) {
            try {
                event.getResource().getSerializer().write(event.getResource().getResponse().getOutputStream(),
                        message);
            } catch (Throwable ex) {
                logger.warn("Serializer exception: message: " + message, ex);
                throw new IOException(ex);
            }
        } else {
            boolean isUsingStream = true;
            if (source.equals("client")) {
                //do nothing
                System.out.println("source is client");
            } else {
                if (event.getResource().getRequest().getAttribute(PROPERTY_USE_STREAM) != null) {
                    isUsingStream = (Boolean) event.getResource().getRequest().getAttribute(PROPERTY_USE_STREAM);
                }

                if (!isUsingStream) {
                    try {
                        r.getWriter();
                    } catch (IllegalStateException e) {
                        isUsingStream = true;
                    }
                }

                if (message instanceof List) {
                    for (String s : (List<String>) message) {
                        if (isUsingStream) {
                            r.getOutputStream().write(s.getBytes(r.getCharacterEncoding()));
                            r.getOutputStream().flush();
                        } else {
                            r.getWriter().write(s);
                            r.getWriter().flush();
                        }
                    }
                } else {
                    if (isUsingStream) {
                        r.getOutputStream().write(message.toString().getBytes(r.getCharacterEncoding()));
                        r.getOutputStream().flush();
                    } else {
                        r.getWriter().write(message.toString());
                        r.getWriter().flush();
                    }
                }
            }

        }
        postStateChange(event);
    }
}