com.laxser.blitz.web.impl.thread.InvocationBean.java Source code

Java tutorial

Introduction

Here is the source code for com.laxser.blitz.web.impl.thread.InvocationBean.java

Source

/*
 * Copyright 2007-2009 the original author or authors.
 *
 * 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 com.laxser.blitz.web.impl.thread;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

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

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import org.springframework.validation.BindingResult;
import org.springframework.web.context.WebApplicationContext;

import com.laxser.blitz.web.Invocation;
import com.laxser.blitz.web.InvocationUtils;
import com.laxser.blitz.web.RequestPath;
import com.laxser.blitz.web.impl.mapping.MatchResult;
import com.laxser.blitz.web.impl.module.Module;
import com.laxser.blitz.web.impl.validation.ParameterBindingResult;
import com.laxser.blitz.web.paramresolver.ParamMetaData;
import com.laxser.blitz.web.var.Flash;
import com.laxser.blitz.web.var.FlashImpl;
import com.laxser.blitz.web.var.Model;
import com.laxser.blitz.web.var.ModelImpl;

/**
 * @author laxser  Date 2012-3-23 ?4:38:52
@contact [duqifan@gmail.com]
@InvocationBean.java
 */
public final class InvocationBean implements Invocation {

    public static final Object[] UN_INITIATED_ARRAY = new Object[0];

    private static final Log logger = LogFactory.getLog(InvocationBean.class);

    private Object[] methodParameters = UN_INITIATED_ARRAY; // ??UN_INITIATED_ARRAY

    private Map<String, Object> attributes;

    private HttpServletRequest request;

    private HttpServletResponse response;

    private RequestPath requestPath;

    private transient Model model;

    private transient Flash flash;

    private Invocation preInvocation;

    private boolean multiPartRequest;

    private List<BindingResult> bindingResults;

    private List<String> bindingResultNames;

    private Blitz blitz;

    private Module viewModule;

    private ActionEngine actionEngine;

    private ControllerEngine controllerEngine;

    private ModuleEngine moduleEngine;

    public InvocationBean(HttpServletRequest request, HttpServletResponse response, RequestPath requestPath) {
        setRequest(request);
        setResponse(response);
        setRequestPath(requestPath);
    }

    public void setBlitz(Blitz blitz) {
        this.blitz = blitz;
    }

    public Blitz getBlitz() {
        return blitz;
    }

    protected boolean isMethodParametersInitiated() {
        return methodParameters != UN_INITIATED_ARRAY;
    }

    @Override
    public WebApplicationContext getApplicationContext() {
        return getModule().getApplicationContext();
    }

    public void setMethodParameters(Object[] methodParameters) {
        this.methodParameters = methodParameters;
    }

    @Override
    public Object getController() {
        ControllerEngine engine = getControllerEngine();
        return engine.getController();
    }

    @Override
    public Class<?> getControllerClass() {
        ControllerEngine engine = getControllerEngine();
        return engine.getControllerClass();
    }

    public Module getModule() {
        return getModuleEngine().getModule();
    }

    public Module getViewModule() {
        return viewModule == null ? getModule() : viewModule;
    }

    public void setViewModule(Module viewModule) {
        this.viewModule = viewModule;
    }

    @Override
    public Method getMethod() {
        return getActionEngine().getMethod();
    }

    @Override
    public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
        return getMethod().isAnnotationPresent(annotationClass)
                || getControllerClass().isAnnotationPresent(annotationClass);
    }

    @Override
    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
        T t = getMethod().getAnnotation(annotationClass);
        if (t == null) {
            t = getControllerClass().getAnnotation(annotationClass);
        }
        return t;
    }

    public ModuleEngine getModuleEngine() {
        if (moduleEngine != null) {
            return moduleEngine;
        }
        return moduleEngine = getEngine(ModuleEngine.class);
    }

    public ControllerEngine getControllerEngine() {
        if (controllerEngine != null) {
            return controllerEngine;
        }
        return controllerEngine = getEngine(ControllerEngine.class);
    }

    public ActionEngine getActionEngine() {
        if (actionEngine != null) {
            return actionEngine;
        }
        return actionEngine = getEngine(ActionEngine.class);
    }

    private <T extends Engine> T getEngine(Class<? extends Engine> engineClass) {
        for (LinkedEngine engine : blitz.getEngines()) {
            if (engine.getTarget().getClass() == engineClass) {
                @SuppressWarnings("unchecked")
                T t = (T) engine.getTarget();
                return t;
            }
        }
        throw new Error("cannot found " + engineClass.getName());
    }

    @Override
    public String[] getMethodParameterNames() {
        return (String[]) ArrayUtils.clone(getActionEngine().getParameterNames());
    }

    @Override
    public Object[] getMethodParameters() {
        return methodParameters;
    }

    @Override
    public Object getMethodParameter(String name) {
        if (!isMethodParametersInitiated()) {
            throw new IllegalStateException();
        }
        String[] names = getActionEngine().getParameterNames();
        for (int i = 0; i < names.length; i++) {
            if (name != null && name.equals(names[i])) {
                return methodParameters[i];
            }
        }
        return null;
    }

    @Override
    public String getParameter(String name) {
        return request.getParameter(name);
    }

    @Override
    public void changeMethodParameter(int index, Object newValue) {
        if (!isMethodParametersInitiated()) {
            throw new IllegalStateException();
        }
        if (newValue != this.methodParameters[index]) {
            if (logger.isDebugEnabled()) {
                String[] names = getActionEngine().getParameterNames();
                logger.debug("change method parameter " + names[index] + " (index=" + index + ") from '"
                        + this.methodParameters[index] + "' to '" + newValue + "'");
            }
            Object oldValue = this.methodParameters[index];
            this.methodParameters[index] = newValue;
            if (logger.isDebugEnabled()) {
                logger.debug("change method parameter at " + index//
                        + ": " + oldValue + "->" + newValue);
            }
        }
    }

    public void changeMethodParameter(String name, Object newValue) {
        if (!isMethodParametersInitiated()) {
            throw new IllegalStateException();
        }
        if (StringUtils.isEmpty(name)) {
            throw new NullPointerException("parameter name");
        }
        String[] names = getActionEngine().getParameterNames();
        for (int i = 0; i < names.length; i++) {
            if (name.equals(names[i])) {
                changeMethodParameter(i, newValue);
                return;
            }
        }
    }

    @Override
    public void changeMethodParameter(ParamMetaData paramMeta, Object newValue) {
        changeMethodParameter(paramMeta.getIndex(), newValue);
    }

    @Override
    public void addModel(Object value) {
        getModel().add(value);
    }

    @Override
    public void addModel(String name, Object value) {
        getModel().add(name, value);
    }

    @Override
    public Model getModel() {
        if (this.model != null) {
            return this.model;
        }
        synchronized (this) {
            ModelImpl model = (ModelImpl) getRequest().getAttribute("$$paoding-blitz.model");
            if (model == null || model.getInvocation() != this) {
                ModelImpl parent = model;
                model = new ModelImpl(this);
                if (parent != null && requestPath.isForwardRequest()) {
                    model.merge(parent.getAttributes());
                }
                getRequest().setAttribute("$$paoding-blitz.model", model);
            }
            this.model = model;
        }
        return this.model;
    }

    @Override
    public Object getModel(String name) {
        return getModel().get(name);
    }

    @Override
    public synchronized Object getAttribute(String name) {
        if (attributes == null) {
            return null;
        }
        return attributes.get(name);
    }

    @Override
    public synchronized void removeAttribute(String name) {
        if (attributes != null) {
            attributes.remove(name);
        }
    }

    @Override
    public synchronized Set<String> getAttributeNames() {
        if (attributes == null) {
            return Collections.emptySet();
        }
        return attributes.keySet();
    }

    @Override
    public synchronized Invocation setAttribute(String name, Object value) {
        if (attributes == null) {
            attributes = new HashMap<String, Object>();
        }
        if (logger.isDebugEnabled()) {
            logger.debug("setAttribute(" + name + "=" + value + ")");
        }
        attributes.put(name, value);
        return this;
    }

    @Override
    public void addFlash(String name, String msg) {
        getFlash(true).add(name, msg);
    }

    @Override
    public Flash getFlash() {
        return getFlash(true);
    }

    public Flash getFlash(boolean create) {
        if (this.flash != null) {
            return this.flash;
        }
        Flash flash = (Flash) getRequest().getAttribute("$$paoding-blitz.flash");
        if (flash == null && create) {
            flash = new FlashImpl(this);
            getRequest().setAttribute("$$paoding-blitz.flash", flash);
        }
        return this.flash = flash;
    }

    @Override
    public RequestPath getRequestPath() {
        return requestPath;
    }

    @Override
    public HttpServletRequest getRequest() {
        return this.request;
    }

    @Override
    public HttpServletResponse getResponse() {
        return response;
    }

    public void setRequest(HttpServletRequest request) {
        if (request == null) {
            throw new NullPointerException("request");
        }
        if (request == this.request) {
            return;
        }
        if (this.request == null) {
            this.request = request;
        } else {
            if (this.request == InvocationUtils.getCurrentThreadRequest()) {
                InvocationUtils.bindRequestToCurrentThread(request);
            }
            this.request = request;
        }
    }

    @Override
    public ServletContext getServletContext() {
        return getModule().getApplicationContext().getServletContext();
    }

    public void setResponse(HttpServletResponse response) {
        this.response = response;
    }

    public void setRequestPath(RequestPath requestPath) {
        this.requestPath = requestPath;
    }

    public Invocation getPreInvocation() {
        return preInvocation;
    }

    public void setPreInvocation(Invocation preInvocation) {
        this.preInvocation = preInvocation;
    }

    @Override
    public Invocation getHeadInvocation() {
        Invocation inv = this;
        while (inv.getPreInvocation() != null) {
            inv = inv.getPreInvocation();
        }
        return inv;
    }

    public void setMultiPartRequest(boolean multiPartRequest) {
        this.multiPartRequest = multiPartRequest;
    }

    public boolean isMultiPartRequest() {
        return multiPartRequest;
    }

    @Override
    public List<BindingResult> getBindingResults() {
        fetchBindingResults();
        return this.bindingResults;
    }

    @Override
    public List<String> getBindingResultNames() {
        fetchBindingResults();
        return this.bindingResultNames;
    }

    @Override
    public BindingResult getParameterBindingResult() {
        return (BindingResult) this.getModel()
                .get(BindingResult.MODEL_KEY_PREFIX + ParameterBindingResult.OBJECT_NAME);
    }

    @Override
    public BindingResult getBindingResult(String name) {
        Assert.notNull(name);
        if (name instanceof String) {
            if (!((String) name).endsWith("BindingResult")) {
                name = name + "BindingResult";
            }
            BindingResult br = (BindingResult) this.getModel().get(BindingResult.MODEL_KEY_PREFIX + name);
            if (br == null) {
                br = getParameterBindingResult();
            }
            return br;
        }
        return null;
    }

    protected void fetchBindingResults() {
        if (this.bindingResults == null) {
            Map<String, Object> attributes = getModel().getAttributes();
            List<String> bindingResultNames = new ArrayList<String>();
            List<BindingResult> bindingResults = new ArrayList<BindingResult>();
            for (String key : attributes.keySet()) {
                if (key.startsWith(BindingResult.MODEL_KEY_PREFIX)) {
                    Object value = attributes.get(key);
                    if (value instanceof BindingResult) {
                        bindingResults.add((BindingResult) value);
                        bindingResultNames.add(((BindingResult) value).getObjectName());
                    }
                }
            }
            this.bindingResults = Collections.unmodifiableList(bindingResults);
            this.bindingResultNames = Collections.unmodifiableList(bindingResultNames);
        }
    }

    @Override
    public String getResourceId() {
        StringBuilder sb = new StringBuilder(255);
        sb.append(getRequest().getContextPath());
        for (MatchResult matchResult : blitz.getMatchResults()) {
            sb.append(matchResult.getMappingNode().getMappingPath());
        }
        return sb.toString();
    }

    @Override
    public void addAfterCompletion(AfterCompletion afterComletion) {
        blitz.addAfterCompletion(afterComletion);
    }

    @Override
    public String toString() {
        return requestPath.getUri();
    }

}