Java tutorial
/* * 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(); } }