org.debux.webmotion.server.WebMotionServer.java Source code

Java tutorial

Introduction

Here is the source code for org.debux.webmotion.server.WebMotionServer.java

Source

/*
 * #%L
 * Webmotion server
 * 
 * $Id$
 * $HeadURL$
 * %%
 * Copyright (C) 2011 - 2015 Debux
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as 
 * published by the Free Software Foundation, either version 3 of the 
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public 
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/lgpl-3.0.html>.
 * #L%
 */
package org.debux.webmotion.server;

import java.io.File;
import org.debux.webmotion.server.call.ServerContext;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.debux.webmotion.server.mapping.Config;
import org.debux.webmotion.server.mbean.ServerStats;
import org.debux.webmotion.server.call.Call;
import org.debux.webmotion.server.call.HttpContext;
import org.debux.webmotion.server.mapping.Mapping;
import org.debux.webmotion.server.websocket.WebSocketInbound;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Main filter manages all call on WebMotion. The servlet invokes two differents 
 * process, the first for classical action management and the other one for static resources.
 * 
 * @author julien
 */
public class WebMotionServer implements Filter {

    private static final Logger log = LoggerFactory.getLogger(WebMotionServer.class);

    /** Path uses to manage action in WebMotion */
    public static final String PATH_DEPLOY = "/deploy";

    /** Path uses to manage error in WebMotion */
    public static final String PATH_ERROR = "/error";

    /** Path uses to manage resources outside WebMotion */
    public static final String PATH_STATIC = "/static";

    /** Path uses to manage servlets outside WebMotion  */
    public static final String PATH_SERVLET = "/servlet";

    /* Servlet name to store delegate to websocket servlet */
    public static final String SERVLET_WEBSOCKET = "wm.websocket";

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // Do nothing
    }

    @Override
    public void destroy() {
        // Do nothing
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpServletRequest = ((HttpServletRequest) request);
        HttpServletResponse httpServletResponse = ((HttpServletResponse) response);
        ServerContext serverContext = getServerContext(httpServletRequest);

        String uri = null;
        DispatcherType dispatcherType = request.getDispatcherType();
        if (dispatcherType == DispatcherType.INCLUDE) {
            uri = (String) httpServletRequest.getAttribute(HttpContext.ATTRIBUTE_INCLUDE_REQUEST_URI);
        }
        if (uri == null) {
            uri = httpServletRequest.getRequestURI();
        }

        String contextPath = httpServletRequest.getContextPath();
        String url = StringUtils.substringAfter(uri, contextPath);
        log.debug("Pass in filter = " + url);

        // Search if url is exclude path
        for (String path : serverContext.getExcludePaths()) {
            if (url.startsWith(path)) {
                url = PATH_SERVLET + url;
                break;
            }
        }

        if (url.startsWith(PATH_DEPLOY) || url.startsWith(PATH_ERROR) || url.equals("/")) {
            log.debug("Is deploy");
            doAction(httpServletRequest, httpServletResponse);

        } else if (url.startsWith(PATH_STATIC)) {
            log.debug("Is static");
            doResource(httpServletRequest, httpServletResponse);

        } else if (url.startsWith(PATH_SERVLET)) {
            log.debug("Is servlet");
            chain.doFilter(request, response);

        } else {
            String webappPath = serverContext.getWebappPath();
            File file = new File(webappPath, url);
            if (file.exists()) {
                // css js html png jpg jpeg xml ...
                log.debug("Is file");
                chain.doFilter(request, response);
            } else {
                log.debug("Is default");
                doAction(httpServletRequest, httpServletResponse);
            }
        }
    }

    /**
     * Action management in the mapping
     */
    protected void doAction(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        long start = System.currentTimeMillis();

        // Create call context use in handler to get information on user request
        ServerContext serverContext = getServerContext(request);
        Call call = new Call(serverContext, request, response);

        // Apply config
        Mapping mapping = serverContext.getMapping();
        applyConfig(mapping, call);

        // Execute the main handler
        WebMotionHandler mainHandler = serverContext.getMainHandler();
        mainHandler.handle(mapping, call);

        // Register call in mbean
        ServerStats serverStats = serverContext.getServerStats();
        serverStats.registerCallTime(call, start);

        // Dispatch on servlet to manage websocket
        WebSocketInbound socket = (WebSocketInbound) request.getAttribute(WebSocketInbound.ATTRIBUTE_WEBSOCKET);
        if (socket != null) {
            ServletContext servletContext = request.getServletContext();
            RequestDispatcher dispatcher = servletContext.getNamedDispatcher(SERVLET_WEBSOCKET);
            dispatcher.forward(request, response);
        }
    }

    /**
     * Apply config in mapping on request and response
     */
    protected void applyConfig(Mapping mapping, Call call) throws WebMotionException {
        HttpContext context = call.getContext();
        HttpServletRequest request = context.getRequest();
        HttpServletResponse response = context.getResponse();

        Config config = mapping.getConfig();
        String encoding = config.getEncoding();
        try {
            request.setCharacterEncoding(encoding);
            response.setCharacterEncoding(encoding);

        } catch (UnsupportedEncodingException encodingException) {
            throw new WebMotionException("Invalid encoding for request", encodingException);
        }
    }

    /**
     * Static resources management
     */
    protected void doResource(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // Suppress the static in path
        HttpServletRequest requestWrapper = new HttpServletRequestWrapper(request) {
            @Override
            public String getServletPath() {
                String servletPath = super.getServletPath();
                if (servletPath != null) {
                    return servletPath.replaceFirst(PATH_STATIC, "");
                }
                return null;
            }

            @Override
            public String getPathInfo() {
                String pathInfo = super.getPathInfo();
                if (pathInfo != null) {
                    return pathInfo.replaceFirst(PATH_STATIC, "");
                }
                return null;
            }

            @Override
            public String getRequestURI() {
                String requestURI = super.getRequestURI();
                if (requestURI != null) {
                    return requestURI.replaceFirst(PATH_STATIC, "");
                }
                return null;
            }
        };

        // Dispatch on default servlet
        ServletContext servletContext = request.getServletContext();
        RequestDispatcher dispatcher = servletContext.getNamedDispatcher("default");

        DispatcherType dispatcherType = request.getDispatcherType();
        if (dispatcherType == DispatcherType.INCLUDE) {
            dispatcher.include(requestWrapper, response);
        } else {
            dispatcher.forward(requestWrapper, response);
        }
    }

    /**
     * @param request request to found servlet context
     * @return server context in servlet context
     */
    protected ServerContext getServerContext(HttpServletRequest request) {
        ServletContext servletContext = request.getServletContext();
        ServerContext serverContext = (ServerContext) servletContext
                .getAttribute(ServerContext.ATTRIBUTE_SERVER_CONTEXT);
        return serverContext;
    }

}