com.ewcms.web.pubsub.PubsubServlet.java Source code

Java tutorial

Introduction

Here is the source code for com.ewcms.web.pubsub.PubsubServlet.java

Source

/**
 * Copyright (c)2010-2011 Enterprise Website Content Management System(EWCMS), All rights reserved.
 * EWCMS PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 * http://www.ewcms.com
 */
package com.ewcms.web.pubsub;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.CometEvent;
import org.apache.catalina.CometProcessor;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Servlet?Tomcat Comet??Tomcat 6.0?<br/>
 * <a href="http://tomcat.apache.org/tomcat-6.0-doc/aio.html">tomcat comet</a>
 * 
 * @author wangwei
 */
public class PubsubServlet extends HttpServlet implements CometProcessor {

    private static final long serialVersionUID = 6492410972635853800L;

    private static final Logger logger = LoggerFactory.getLogger(PubsubServlet.class);
    private static final String INITIALDELAY_PARAM_NAME = "initialDelay";
    private static final String DELAY_PARAM_NAME = "delay";
    private static final String PUBSUB_CONTEXT = "pubsub";

    private final Map<String, String> pathSender = new HashMap<String, String>();
    private final Map<String, PubsubSenderable> senders = Collections
            .synchronizedMap(new HashMap<String, PubsubSenderable>());

    private long initialDelay = 5;
    private long delay = 15;

    private void initInitialDelay() {
        String value = this.getInitParameter(INITIALDELAY_PARAM_NAME);
        if (StringUtils.isNumeric(value)) {
            initialDelay = Long.valueOf(value);
        }
    }

    private void initDelay() {
        String value = this.getInitParameter(DELAY_PARAM_NAME);
        if (StringUtils.isNumeric(value)) {
            delay = Long.valueOf(value);
        }
    }

    private void initPathMapSender() {
        Enumeration<?> names = this.getInitParameterNames();
        for (; names.hasMoreElements();) {
            String path = (String) names.nextElement();
            if (path.equals(INITIALDELAY_PARAM_NAME) || path.equals(DELAY_PARAM_NAME)) {
                continue;
            }
            String className = this.getInitParameter(path);
            String pubSubPath = StringUtils.substringAfter(path, PUBSUB_CONTEXT);
            pathSender.put(pubSubPath, className);
        }
    }

    @Override
    public void init() throws ServletException {
        initInitialDelay();
        initDelay();
        initPathMapSender();
    }

    @Override
    public void destroy() {
    }

    /**
     * Comet event?
     * 
     * ???<a href = "http://tomcat.apache.org/tomcat-6.0-doc/aio.html#Example_code">ChatServlet</a>
     * 
     * @param event
     *            The Comet event that will be processed
     * @throws IOException
     * @throws ServletException
     */
    public void event(CometEvent event) throws IOException, ServletException {
        HttpServletRequest request = event.getHttpServletRequest();
        HttpServletResponse response = event.getHttpServletResponse();

        if (event.getEventType() == CometEvent.EventType.BEGIN) {
            logger.debug("Begin for session:{} ", request.getSession(true).getId());
            String fullContentType = "text/html;charset=UTF-8";
            response.setContentType(fullContentType);
            addConnection(request.getPathInfo(), response);
        } else if (event.getEventType() == CometEvent.EventType.ERROR) {
            logger.debug("Error for session: {}", request.getSession(true).getId());
            removeConnection(response);
            event.close();
        } else if (event.getEventType() == CometEvent.EventType.END) {
            logger.debug("End for session:{} ", request.getSession(true).getId());
            removeConnection(response);
            event.close();
        } else if (event.getEventType() == CometEvent.EventType.READ) {
            InputStream is = request.getInputStream();
            byte[] buf = new byte[512];
            do {
                int n = is.read(buf); // can throw an IOException
                if (n > 0) {
                    logger.debug("Read {} bytes:{} for session:{}",
                            new Object[] { n, new String(buf, 0, n), request.getSession(true).getId() });
                } else if (n < 0) {
                    return;
                }
            } while (is.available() > 0);
        }
    }

    private PubsubSenderable createPubsubSender(String path) {
        String name = null;
        if (StringUtils.indexOf(path, '/') == -1) {
            name = pathSender.get(path);
        } else {
            String root = StringUtils.substringBeforeLast(path, "/");
            name = pathSender.get(root);
            if (name == null) {
                String middle = StringUtils.substringAfter(root, "/");
                name = pathSender.get(middle);
            }
        }
        if (StringUtils.isNotBlank(name)) {
            try {
                Class<?> clazz = Class.forName(name);
                Class<?>[] argsClass = new Class<?>[] { String.class, ServletContext.class };
                Constructor<?> cons = clazz.getConstructor(argsClass);
                return (PubsubSenderable) cons.newInstance(new Object[] { path, this.getServletContext() });
            } catch (Exception e) {
                logger.error("PubsubSender create error:{}", e.toString());
            }
        }

        return new NoneSender();
    }

    private void addConnection(String path, HttpServletResponse connection) {
        synchronized (senders) {
            PubsubSenderable sender = senders.get(path);
            if (sender == null) {
                sender = createPubsubSender(path);
                sender.setDelay(delay);
                sender.setInitialDelay(initialDelay);
                sender.start();
                senders.put(path, sender);
            }
            sender.addClient(connection);
        }
    }

    private void removeConnection(HttpServletResponse connection) {
        synchronized (senders) {
            for (PubsubSenderable sender : senders.values()) {
                sender.removeClient(connection);
            }
        }
    }
}