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

net.contextfw.web.application.internal.service.WebApplicationImpl Maven / Gradle / Ivy

package net.contextfw.web.application.internal.service;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;

import net.contextfw.web.application.HttpContext;
import net.contextfw.web.application.WebApplicationException;
import net.contextfw.web.application.WebApplicationHandle;
import net.contextfw.web.application.component.Component;
import net.contextfw.web.application.component.DOMBuilder;
import net.contextfw.web.application.configuration.Configuration;
import net.contextfw.web.application.internal.ComponentUpdateHandler;
import net.contextfw.web.application.internal.ComponentUpdateHandlerFactory;
import net.contextfw.web.application.internal.WebResponder;
import net.contextfw.web.application.internal.WebResponder.Mode;
import net.contextfw.web.application.internal.component.ComponentBuilder;
import net.contextfw.web.application.internal.component.ComponentRegister;
import net.contextfw.web.application.internal.component.WebApplicationComponent;
import net.contextfw.web.application.internal.initializer.InitializerContextImpl;
import net.contextfw.web.application.internal.util.AttributeHandler;
import net.contextfw.web.application.lifecycle.PageScoped;
import net.contextfw.web.application.lifecycle.ResourceView;
import net.contextfw.web.application.remote.ResourceBody;
import net.contextfw.web.application.remote.ResourceResponse;
import net.contextfw.web.application.util.Request;

import com.google.gson.Gson;
import com.google.inject.Inject;
import com.google.inject.Injector;

@PageScoped
public class WebApplicationImpl implements WebApplication {

    @Inject
    private Gson gson;
    
    @Inject
    private ComponentUpdateHandlerFactory euhf;

    @Inject
    private ComponentBuilder builder;

    private static volatile Map updateHandlers = new HashMap();

    @Inject
    private Injector injector;

    @Inject
    private HttpContext httpContext;

//    @Inject
//    private PageFlowFilter pageFlowFilter;

    private final ComponentRegister componentRegister = new ComponentRegister();

    private final WebApplicationComponent rootComponent =
            new WebApplicationComponent(componentRegister);

    private List> chain;

    private InitializerContextImpl context;

    @Inject
    private WebResponder responder;

    private Mode mode = Mode.INIT;

    @Inject
    private AttributeHandler attributes;

    @Inject
    private WebApplicationHandle webApplicationHandle;

    //private final String contextPath;
    
    private final String xmlParamName;
    
    private final boolean debugMode;
    
    @Inject
    public WebApplicationImpl(Configuration props) {
        xmlParamName = props.get(Configuration.XML_PARAM_NAME);
        debugMode = props.get(Configuration.DEVELOPMENT_MODE);
    }

    @Override
    public void initState() throws WebApplicationException {
        context = new InitializerContextImpl(injector, chain);
        rootComponent.registerChild(context.initChild());
    }

    @Override
    public boolean sendResponse() {

        try {
            if (mode == Mode.INIT) {
                if (httpContext.getRedirectUrl() != null) {
                    httpContext.getResponse().sendRedirect(httpContext.getRedirectUrl());
                    return true;
                } else if (httpContext.getErrorCode() != null) {
                    httpContext.getResponse().sendError(httpContext.getErrorCode(), httpContext.getErrorMsg());
                    return true;
                } else if (httpContext.isReload()) {
                    httpContext.getResponse().sendRedirect(httpContext.getRequestURI() 
                            + httpContext.getQueryString() == null ? "" : "?" + httpContext.getQueryString());
                }
            }

            try {
                if (mode == Mode.INIT && context.getLeaf() instanceof ResourceView) {
                    return sendResourceResponse();
                } else {
                    sendNormalResponse();
                    return false;
                }
            } catch (Exception e) {
                if (e instanceof WebApplicationException) {
                    throw (WebApplicationException) e;
                } else {
                    throw new WebApplicationException("Exception while trying to init state", e);
                }
            }

        } catch (IOException e) {
            throw new WebApplicationException(e);
        }
    }

    private boolean sendResourceResponse() throws IOException {
        boolean expire = true;
        
        ResourceView leaf = (ResourceView) context.getLeaf();
        try {
            ResourceBody annotation = leaf.getClass().getMethod("getResponse")
                .getAnnotation(ResourceBody.class);
            
            if (annotation != null) {
                expire = annotation.expire();
            }
        } catch (SecurityException e) {
            throw new WebApplicationException(e);
        } catch (NoSuchMethodException e) {
            throw new WebApplicationException(e);
        }
        
        Object retVal = leaf.getResponse();
        if (retVal == null) {
            return expire;
        }
        if (retVal instanceof ResourceResponse) {
            ((ResourceResponse) retVal).serve(
                    httpContext.getRequest(), 
                    httpContext.getResponse());
        } else {
            HttpServletResponse response = httpContext.getResponse();
            setHeaders(response);
            response.setContentType("application/json; charset=UTF-8");
            gson.toJson(retVal, response.getWriter());
        }
        return expire;
    }

    private void sendNormalResponse() throws ServletException, IOException {
        httpContext.getResponse().setContentType("text/html; charset=UTF-8");

        DOMBuilder d;

        if (mode == Mode.INIT) {
            d = new DOMBuilder("WebApplication", attributes, builder);
        } else {
            d = new DOMBuilder("WebApplication.update", attributes, builder);
        }

        d.attr("handle", webApplicationHandle.getKey());
        d.attr("contextPath", httpContext.getRequest().getContextPath());

        if (context.getLocale() != null) {
            d.attr("xml:lang", context.getLocale().toString());
            d.attr("lang", context.getLocale().toString());
        }
        if (mode == Mode.INIT) {
            rootComponent.buildChild(d);
        } else if (httpContext.getRedirectUrl() != null) {
            d.descend("Redirect").attr("href", httpContext.getRedirectUrl());
        } else if (httpContext.getErrorCode() != null) {
            d.descend("Error").attr("code", httpContext.getErrorCode()).text(httpContext.getErrorMsg());
        } else if (httpContext.isReload()) {
            d.descend("Reload");
        } else {
            rootComponent.buildChildUpdate(d, builder);
        }

        rootComponent.clearCascadedUpdate();

        if (xmlParamName == null
                || httpContext.getRequest().getParameter(xmlParamName) == null) {
            responder.sendResponse(d.toDocument(), httpContext.getResponse(), mode);
        } else {
            responder.sendResponse(d.toDocument(), httpContext.getResponse(), Mode.XML);
        }
    }

    @Override
    public UpdateInvocation updateState(boolean updateComponents, String componentId, String method) throws WebApplicationException {
        mode = Mode.UPDATE;
        if (updateComponents) {
            return updateElements(componentId, method);
        } else {
            return UpdateInvocation.NOT_DELAYED;
        }
    }

    @SuppressWarnings("unchecked")
    protected UpdateInvocation updateElements(final String id, final String method) throws WebApplicationException {
        try {
            Request request = new Request(httpContext.getRequest());
            Component element = componentRegister.findComponent(id);
            String key = ComponentUpdateHandler.getKey(element.getClass(), method);

                if (!updateHandlers.containsKey(key) || debugMode) {
                    updateHandlers.put(key, euhf.createHandler(element.getClass(), method));
                }

                ComponentUpdateHandler handler = updateHandlers.get(key);

                if (handler != null) {
                    if (handler.getDelayed() == null
                                || !injector.getInstance(handler.getDelayed().value())
                                  .isUpdateDelayed(element, httpContext.getRequest())) {
                        return new UpdateInvocation(
                                handler.isResource(),
                                handler.invoke(element, request)
                                );
                    } else {
                        return UpdateInvocation.DELAYED;
                    }
                } else {
                    return UpdateInvocation.NOT_DELAYED;
                }
        } catch (Exception e) {
            if (e instanceof WebApplicationException) {
                throw (WebApplicationException) e;
            } else {
                throw new WebApplicationException("Failed to update elements", e);
            }
        }
    }

    @Override
    public void setInitializerChain(List> chain) {
        this.chain = chain;
    }
    
    public void setHeaders(HttpServletResponse response) {
        response.addHeader("Expires", "Sun, 19 Nov 1978 05:00:00 GMT");
        response.addHeader("Last-Modified", new Date().toString());
        response.addHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        // response.addHeader("Cache-Control","post-check=0, pre-check=0");
        response.addHeader("Pragma", "no-cache");
        response.setHeader("Connection", "Keep-Alive");
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy