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

org.cometd.server.CometdServlet Maven / Gradle / Ivy

// ========================================================================
// Copyright 2007 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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.cometd.server;

import java.io.IOException;
import java.util.HashSet;
import java.util.Map;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.cometd.bayeux.Transport;
import org.cometd.bayeux.server.BayeuxServer;
import org.cometd.bayeux.server.ServerMessage;
import org.cometd.server.transports.HttpTransport;
import org.cometd.server.transports.JSONPTransport;
import org.cometd.server.transports.JSONTransport;
import org.cometd.server.transports.WebSocketTransport;

/**
 */
public class CometdServlet extends GenericServlet
{
    public static final int CONFIG_LEVEL=1;
    public static final int INFO_LEVEL=2;
    public static final int DEBUG_LEVEL=3;
    public static final String CLIENT_ATTR="org.cometd.server.client";
    public static final String TRANSPORT_ATTR="org.cometd.server.transport";
    public static final String MESSAGE_PARAM="message";
    public static final String TUNNEL_INIT_PARAM="tunnelInit";
    public static final String HTTP_CLIENT_ID="BAYEUX_HTTP_CLIENT";

    private final BayeuxServerImpl _bayeux = new BayeuxServerImpl();
    private final JSONTransport _lpTransport = new JSONTransport(_bayeux,_bayeux.getOptions());
    private final JSONPTransport _cbTransport = new JSONPTransport(_bayeux,_bayeux.getOptions());
    private final WebSocketTransport _wsTransport = new WebSocketTransport(_bayeux,_bayeux.getOptions());
    private final ThreadLocal _currentRequest = new ThreadLocal();
    private String _transportParameter;
    private String _callbackParameter;
    private boolean _useWS;
    private boolean _useLP;
    private boolean _useCB;
    private int _logLevel;
    
    
    public BayeuxServerImpl getBayeux()
    {
        return _bayeux;
    }

    protected void initializeBayeux(BayeuxServerImpl bayeux)
    {
        bayeux.addTransport(_wsTransport);
        bayeux.addTransport(_lpTransport);
        bayeux.addTransport(_cbTransport);
        bayeux.setAllowedTransports(WebSocketTransport.NAME,JSONTransport.NAME,JSONPTransport.NAME);
    }

    @Override
    public void init() throws ServletException
    {
        if (getInitParameter("logLevel")!=null)
        {
            _logLevel=Integer.parseInt(getInitParameter("logLevel"));
            if (_logLevel>=DEBUG_LEVEL)
                _bayeux.getLogger().setDebugEnabled(true);
        }
        
        initializeBayeux(_bayeux);
        getServletContext().setAttribute(BayeuxServer.ATTRIBUTE,_bayeux);
        
        // Get any specific options as init paramters
        HashSet qualified_names = new HashSet();
        for (String name :_bayeux.getKnownTransportNames())
        {
            Transport transport = _bayeux.getTransport(name);
            {
                for (String option : transport.getOptionNames())
                {
                    qualified_names.add(option);
                    String prefix=transport.getOptionPrefix();
                    while (prefix!=null)
                    {
                        qualified_names.add(prefix+"."+option);
                        int dot=prefix.lastIndexOf('.');
                        prefix=dot<0?null:prefix.substring(0,dot);
                    }
                }
            }
        }
        
        for (String option : qualified_names)
        {
            Object value = getInitParameter(option);
            if (value!=null)
                _bayeux.setOption(option,value);
        }

        for (String name :_bayeux.getKnownTransportNames())
        {
            Transport transport = _bayeux.getTransport(name);
            if (transport instanceof ServerTransport)
                ((ServerTransport)transport).init();
        }
        
        if (_logLevel>=CONFIG_LEVEL)
        {
            for (Map.Entry entry : _bayeux.getOptions().entrySet())
                getServletContext().log(entry.getKey()+"="+entry.getValue());
        }
        
        _useLP=_bayeux.getAllowedTransports().contains(JSONTransport.NAME);
        _useCB=_bayeux.getAllowedTransports().contains(JSONPTransport.NAME);
        _useWS=_bayeux.getAllowedTransports().contains(JSONPTransport.NAME);
        _callbackParameter=(String)_cbTransport.getCallbackParameter();
        
        try
        {
            _bayeux.start();
        }
        catch(Exception e)
        {
            throw new ServletException(e);
        }
    }

    @Override
    public void service(ServletRequest req, ServletResponse resp) throws ServletException, IOException
    {
        HttpServletRequest request=(HttpServletRequest)req;
        HttpServletResponse response=(HttpServletResponse)resp;

        _currentRequest.set(request);
        try
        {
            service(request,response);
        }
        finally
        {
            _currentRequest.set(null);
        }
    }

    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        HttpTransport transport=null;
        
        // handle forced transport
        if (_transportParameter!=null)
        {
            String transport_name=request.getParameter(_transportParameter);
            if (transport_name!=null)
                transport= (HttpTransport)_bayeux.getTransport(transport_name);
        }
        
        if (transport==null)
        {
            if (_useCB && request.getParameter(_callbackParameter)!=null)
                transport=_cbTransport;
            else if (_useWS && "WebSocket".equals(request.getHeader("Upgrade")))
                transport=_wsTransport;
            else if (_useLP)
                transport=_lpTransport;
        }
            
        if (transport==null)         
            response.sendError(400,"bad transport");
        else
        {
            try
            {
                _bayeux.setCurrentTransport(transport);
                transport.setCurrentRequest(request);
                transport.handle(request,response);
            }
            finally
            {
                _bayeux.setCurrentTransport(null);  
                transport.setCurrentRequest(null);
            }
        }
    }


    private static ServerMessage.Mutable[] __EMPTY_BATCH=new ServerMessage.Mutable[0];

    protected ServerMessage.Mutable[] getMessages(HttpServletRequest request) throws IOException
    {
        String fodder=null;
        try
        {
            // Get message batches either as JSON body or as message parameters
            if (request.getContentType() != null && !request.getContentType().startsWith("application/x-www-form-urlencoded"))
            {
                return _bayeux.getServerMessagePool().parseMessages(request.getReader());
            }

            String[] batches=request.getParameterValues(MESSAGE_PARAM);

            if (batches == null || batches.length == 0)
                return __EMPTY_BATCH;

            if (batches.length == 0)
            {
                fodder=batches[0];
                return _bayeux.getServerMessagePool().parseMessages(fodder);
            }

            throw new IllegalStateException();
        }
        catch(IOException e)
        {
            throw e;
        }
        catch(Exception e)
        {
            throw new Error(fodder,e);
        }
    }

    /* ------------------------------------------------------------ */
    /**
     * @see javax.servlet.GenericServlet#destroy()
     */
    @Override
    public void destroy()
    {
        for (ServerSessionImpl session : _bayeux.getSessions())
        {
            session.cancelDispatch();
        }
        
    }
    
    

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy