package org.theonefx.wcframework.mvc.wcweb; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.servlet.ServletContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.theonefx.wcframework.core.ClassWrapper; import org.theonefx.wcframework.core.exception.InpossibleException; import org.theonefx.wcframework.core.exception.UnFinishException; import org.theonefx.wcframework.mvc.MVCConfig; import org.theonefx.wcframework.mvc.annotation.Action; import org.theonefx.wcframework.mvc.annotation.Controller; import org.theonefx.wcframework.mvc.annotation.PathMatchType; import org.theonefx.wcframework.mvc.annotation.Result; import org.theonefx.wcframework.mvc.exception.ActionInvocationException; import org.theonefx.wcframework.mvc.exception.MVCException; import org.theonefx.wcframework.mvc.wcweb.view.BasicAuthoView; import org.theonefx.wcframework.mvc.wcweb.view.ForwardView; import org.theonefx.wcframework.mvc.wcweb.view.JSONView; import org.theonefx.wcframework.mvc.wcweb.view.NULLView; import org.theonefx.wcframework.mvc.wcweb.view.RedirectActionView; import org.theonefx.wcframework.mvc.wcweb.view.RedirectView; import org.theonefx.wcframework.utils.StringUtils; /** * @File : ControllerRegister.java * @ClassName : ControllerRegister * @Author : 陈曦 * @Date : 2012-4-1 下午02:31:21 * @Version : v1.0 * @Description : 控制器注册器。控制器可以是一个Action,也可以是过滤器。二者都可以返回一个View对象 */ public class ControllerRegister { private final Log log = LogFactory.getLog(getClass()); private final List<ActionInvoker> actions = new ArrayList<ActionInvoker>(); private final List<FilterInvoker> filters = new ArrayList<FilterInvoker>(); @SuppressWarnings("unused") private ServletContext servletContext; public ControllerRegister(ServletContext servletContext) { this.servletContext = servletContext; } public void registAction(Method method, Action action, ClassWrapper<?> wrapper, String beanId, Controller controller) { PathMatchType matchType = action.matchType(); String path = action.path(); // 没有指明path就是用方法名的小写 if (StringUtils.isBlank(path)) { path = method.getName().toLowerCase(); } // 检查namespace // 如果namespace不存在,那么就是跟,即:"/" String namespace = "/"; if (controller != null) { namespace = StringUtils.isBlank(controller.namespace()) ? "/" : controller.namespace(); } // 首先检查path是否是"/"开头 // 如果是"/"开头则忽略namespace // 否则添加namespace信息,如果namespace没有"/"开头,则给namespace增加"/"开头 // 但是如果没有"/"开头,也没有namespace则默认添加"/"开头 if (!path.startsWith("/") && StringUtils.isNotBlank(namespace)) { if (!namespace.endsWith("/")) { namespace = namespace + "/"; } if (!namespace.startsWith("/")) { namespace = "/" + namespace; } path = namespace + path; } else if (!path.startsWith("/") && StringUtils.isBlank(namespace)) { path = "/" + path; } else { // 这个else都是以/开头的情况了,直接忽略namespace } PathMatcher matcher = null; switch (matchType) { case ABSOLUTE: matcher = new AbsolutePathMatcher(path); break; case SIMPLE: matcher = new SimplePathMatcher(path); break; case PATTERN: matcher = new PatternPathMatcher(path); break; case SMART: matcher = new SmartPathMatcher(path); break; } ActionInvoker invoker = new ActionInvoker(matcher); invoker.setBeanId(beanId); // 设置编码参数 if (!org.theonefx.wcframework.mvc.annotation.Action.DefaultEncoding.equals(action.encoding())) { invoker.setEncoding(action.encoding()); } invoker.setMethod(method); invoker.setNameSpace(namespace); invoker.setClassWrapper(wrapper); // 局部Result Result[] results = action.result(); // 全局Result Result[] globalResults = {}; if (controller != null && controller.result() != null) { globalResults = controller.result(); } ArrayList<View> viewsArray = new ArrayList<View>(); Set<String> registedResultNames = new HashSet<String>(); for (int i = 0; i < (results.length + globalResults.length); i++) { Result result = null; if (i < results.length) { result = results[i]; } else { result = globalResults[i - results.length]; } // 不能重复的名称,因为会先取局部后取全局,所以会用子的覆盖全局的 if (registedResultNames.contains(result.name())) { continue; } View view = getView(result); String encoding = result.encoding(); if (!Result.DefaultEncoding.equals(encoding)) { if (encoding == null) { encoding = MVCConfig.defaultEncoding; } view.setEncoding(encoding); } view.setIgnoreEl(result.ignoreEl()); registedResultNames.add(result.name()); viewsArray.add(view); } if (viewsArray.size() == 0) { throw new MVCException("Action[" + method.getDeclaringClass().getName() + "." + method.getName() + "]没有对应的视图(局部的和全局的都没有)"); } invoker.setViews(viewsArray.toArray(new View[viewsArray.size()])); addAction(invoker); // TODO FilteBy还没搞完 } private void addAction(ActionInvoker invoker) { for (ActionInvoker in : actions) { if (in.getMatcher().sameAs(invoker.getMatcher())) { throw new MVCException("定义了两个一样的Action于相同的Matcher"); } } try { invoker.initialize(); } catch (Exception e) { throw new ActionInvocationException("创建ActionInvoker出错:Class=", e); } if (log.isDebugEnabled()) { log.debug("注册Action,Path=" + invoker.getMatcher().getExpression() + " Method=" + invoker.getMethod().getDeclaringClass().getName() + "." + invoker.getMethod().getName()); } actions.add(invoker); } private void addFilter(FilterInvoker invoker) { for (FilterInvoker in : filters) { if (in.getPathMatcher().sameAs(invoker.getPathMatcher()) && StringUtils.equal(in.getBeanId(), invoker.getBeanId())) { throw new MVCException("定义了两个一样的Filter于相同的path"); } } try { invoker.initialize(); } catch (Exception e) { throw new ActionInvocationException("创建FilterInvoker出错:Class=", e); } filters.add(invoker); } public void registFilter(org.theonefx.wcframework.mvc.annotation.Filter filter, ClassWrapper<?> wrapper, String beanId) { FilterInvoker invoker = new FilterInvoker(); switch (filter.matchType()) { case ABSOLUTE: invoker.setPathMatcher(new AbsolutePathMatcher(filter.match())); break; case PATTERN: invoker.setPathMatcher(new PatternPathMatcher(filter.match())); break; case SIMPLE: invoker.setPathMatcher(new SimplePathMatcher(filter.match())); break; default: throw new InpossibleException("怎么可能"); } invoker.setBeanId(beanId); Result[] results = filter.result(); View[] views = new View[results.length]; for (int i = 0; i < results.length; i++) { Result result = results[i]; views[i] = getView(result); } invoker.setLevel(filter.level()); invoker.setViews(views); addFilter(invoker); } private View getView(Result result){ View view = null; switch (result.type()) { case FORWARD: view = new ForwardView(result.name(), result.value(), result.contextType()); break; case REDIRECT: view = new RedirectView(result.name(), result.value(), result.contextType()); break; case REDIRECTACTION: view = new RedirectActionView(result.name(), result.value(), result.contextType()); break; case JSON: view = new JSONView(result.name(), result.contextType()); break; case NULL: view = new NULLView(result.name(), result.contextType()); break; case BASICAUTHO: view = new BasicAuthoView(result.name(), result.contextType()); break; default: // 其实都实现了,不过这里不改了,出这个异常也不可能的。。。。 throw new UnFinishException(); } return view; } public List<FilterInvoker> getFilters() { return filters; } public List<ActionInvoker> getActions() { return actions; } public void refresh() { synchronized (actions) { Collections.sort(actions); } } }