Package mfinder.impl

Source Code of mfinder.impl.DefaultActionFactory$ActionCacheEntry

/*
* Copyright (C) 2010-2011 sunjumper@163.com
*
* 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 mfinder.impl;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import mfinder.ActionFactory;
import mfinder.ActionInvocation;
import mfinder.MFinderException;
import mfinder.ObjectFactory;
import mfinder.annotation.Action;
import mfinder.annotation.Interceptor;
import mfinder.annotation.InterceptorStack;
import mfinder.annotation.Namespace;
import mfinder.annotation.Result;
import mfinder.annotation.ResultType;
import mfinder.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* 默认ActionFactory的实现类,以‘/’作为路径的分隔符。
* DefaultActionFactory中的加载和调用的拦截器、结果类型对象均为单例;
* {@link Action}对象根据其{@link Action#scope()}属性判断是否单例。
* DefaultActionFactory中的Action、拦截器、拦截栈及结果类型的集合在初始化时加载完成,
* 之后任何情况下DefaultActionFactory不再执行集合的修改和删除操作。对返回集合进行的修改和删除请自行保证其线程安全性。
*/
public class DefaultActionFactory implements ActionFactory {

    /** 日志 */
    private static final Logger LOG = LoggerFactory.getLogger(DefaultActionFactory.class);

    /** 路径分隔符 */
    public static final char PATH_SEPARATOR = '/';

    /** 全匹配标识 */
    private String match = PathTree.SINGLE_MATCH;

    /** 路径后缀,默认为'.';非空时截断路径后缀 */
    private String extension = ".";

    /**
     * Action运行时上下文的类型,用于传递上下文参数时的界限判断。
     * 未指定参数类型即null时表示允许ActionInvocation类型的任意子类。
     */
    private Class<? extends ActionInvocation> actionInvocationClass;

    /**
     * 默认拦截栈名称。
     * 默认拦截栈名称的设置仅在初始化Action时,更改默认拦截栈名称仅影响以后加载的Action。
     *
     * @see #createActionProxy(Method, Object)
     */
    private String defaultInterceptorStack = null;

    /**
     * 默认视图类型。
     * 默认视图类型的更改影响每次调用。
     *
     * @see #invokeAction(String, Object[])
     */
    private String defaultResultType = null;

    /**
     * {@link #actionCache}最大缓存数目,默认最大缓存50w条记录;缓存数目小于0则无缓存。
     */
    private int actionCacheNumber = 500000;

    /**
     * 创建对象的工厂对象。
     */
    private ObjectFactory objectFactory = new ObjectFactory() {

        @Override
        public <T> T newInstance(Class<T> clazz) {
            try {
                return clazz.newInstance();
            } catch (IllegalAccessException e) {
                throw new MFinderException(e, null);
            } catch (InstantiationException e) {
                throw new MFinderException(e, null);
            }
        }
    };
////////////////////////////////////////////////////////////////////////////////

    /** 拦截器 */
    private final Map<String, InterceptorProxy> interceptors = new HashMap<String, InterceptorProxy>();

    /** 拦截栈 */
    private final Map<String, InterceptorStackProxy> interceptorStacks = new HashMap<String, InterceptorStackProxy>();

    /** 实际的Action树结构路径映射 */
    private final PathTreeMap<ActionProxy> actions = new PathTreeMap<ActionProxy>(PATH_SEPARATOR);

    /** Action路径与代理对象的映射缓存 */
    private final Map<String, ActionCacheEntry> actionCache = new java.util.concurrent.ConcurrentHashMap<String, ActionCacheEntry>(10000);

    /** 结果类型 */
    private final Map<String, ResultTypeProxy> resultTypes = new HashMap<String, ResultTypeProxy>();

    /** 默认的全局结果对象集合 */
    private final Map<String, ResultProxy> results = new HashMap<String, ResultProxy>();

    /**
     * 通过路径调用相应的Action,可以传递Action代理方法相应的参数。
     * Action调用是否为线程安全取决于路径所映射方法的线程安全性。
     *
     * @param path Action的映射路径。
     * @param params Action的调用参数。
     *
     * @return 调用后的结果;如果结果为字符串类型非空且存在结果对象,则查找相应的结果类型并返回调用后的结果;
     * 反之直接返回结果。
     *
     * @throws MFinderException 如果发生调用错误。
     */
    @Override
    public Object invokeAction(String path, Object... params) throws MFinderException {
        //remove the extension
        if (StringUtil.isNotNull(extension)) {
            int len = extension.length();
            //extension为特定的标记字符,则截去标记字符后的部分
            if (len == 1 && !Character.isLetterOrDigit(extension.charAt(0))) {
                int index = path.lastIndexOf(extension.charAt(0));
                if (index != -1) {
                    path = path.substring(0, index);
                }
            } else {
                //extension为特定的后缀字符串
                if (path.endsWith(extension)) {
                    //extension前一位非字母或数字
                    if (!Character.isLetterOrDigit(path.charAt(path.length() - len - 1))) {
                        len++;
                    }
                    path = path.substring(0, path.length() - len);
                }
            }
        }

        //create ActionInvocation
        ActionInvocation invocation = createActionInvocation(path, params);

        //invoke
        Object res = null;
        try {
            res = invocation.invoke(params);
            //result is string
            if (res instanceof String) {
                String resInfo = res.toString();
                ActionProxy ap = invocation.getActionProxy();
                Result result = null;

                //如果action中存在相应的结果映射
                if ((result = ap.getResults().get(resInfo)) != null) {
                    //调用结果对象相应的结果类型
                    Object rr = invokeByResult(invocation, result);
                    if (rr != null)
                        res = rr;
                } //如果Action调用结果的路径信息中包含':'可省略Action中的@Result(name = "*"...)
                else if ((result = ap.getResults().get(match)) != null || resInfo.indexOf(':') != -1) {
                    //非完全匹配字符串路径的调用
                    Object rr = invokeByString(invocation, result, resInfo);
                    if (rr != null)
                        res = rr;
                } //如果全局结果对象集合中存在相应的结果映射
                else if (results.containsKey(resInfo)) {
                    ResultProxy rp = results.get(resInfo);
                    Object rr = rp.invoke(rp.isRequireAction() ? invocation : null);
                    if (rr != null)
                        res = rr;

                    result = rp.getResult();
                    //当Result的type值不为空时,执行相应的ResultType
                    if (StringUtil.isNotNull(result.type())) {
                        rr = invokeByResult(invocation, result);
                        if (rr != null)
                            res = rr;
                    }
                } else {
                    //若无匹配
                    Object rr = invokeUndefinedResult(invocation, resInfo);
                    if (rr != null)
                        res = rr;
                }
            } else {
                //非字符串结果的对象处理方式
                Object rr = invokeObjectResult(invocation, res);
                if (rr != null)
                    res = rr;
            }
        } catch (InvocationProxyException e) {
            //去除不必要的InvocationProxyException异常,封装异常的源并抛出。
            throw new InvocationProxyException(e.getSource(), null);
        }
        return res;
    }

    /**
     * 创建Action调用时的上下文对象。
     *
     * @param path Action的映射路径。
     * @param params Action的调用参数。
     *
     * @return Action调用时的上下文对象。
     */
    protected ActionInvocation createActionInvocation(String path, Object... params) {
        //cache
        ActionCacheEntry ace = null;
        if (actionCacheNumber > 0)
            ace = actionCache.get(path);

        //Action代理对象
        ActionProxy ap = null;
        //路径的参数匹配映射
        Map<String, String> matchParameters = null;

        //get from cache
        if (ace != null) {
            ap = ace.actionProxy;
            matchParameters = ace.matchParameters;
        } else {
            //initiate matchParameters
            matchParameters = new HashMap<String, String>(5);
            ap = actions.get(path, matchParameters);
            //set matchParameters null if empty
            if (matchParameters.isEmpty())
                matchParameters = null;

            if (ap == null)
                throw new MFinderException("No such Action : " + path, null);

            //put in cache
            ace = new ActionCacheEntry(ap, matchParameters);
            putActionCache(path, ace);
        }

        //scope action
        ap = ap.getInstance();
        //未完成 actionInvocationClass ???
        //create DefaultActionInvocation
        return new DefaultActionInvocation(this, ap, matchParameters, params);
    }

    /**
     * 调用Result相应的ResultType。
     *
     * @param invocation Action运行时上下文。
     * @param result 结果对象。
     *
     * @return 调用ResultType后的结果。
     */
    private Object invokeByResult(ActionInvocation invocation, Result result) {
        String type = result.type();
        //default result type
        if (StringUtil.isNull(type))
            type = defaultResultType;

        ResultTypeProxy rtp = resultTypes.get(type);
        if (rtp == null)
            throw new MFinderException("No such ResultType [" + type + "] at : "
                    + invocation.getActionProxy().getMethodInfo(), invocation.getActionProxy());

        if (rtp.isRequireAction()) {
            ((DefaultActionInvocation) invocation).setResult(result);
        }
        //结果类型调用
        return rtp.invoke(rtp.isRequireAction() ? invocation : null);
    }

    /**
     * 提供非完全匹配路径的结果对象的调用方式。
     * 默认提供全字符串结果的匹配处理。
     *
     * @param invocation Action运行时上下文。
     * @param result Action调用完成后的结果对象。
     * @param pathinfo Action调用的结果对象的路径信息。
     *
     * @return 调用相应结果类型后的值,无匹配则返回 null。
     */
    private Object invokeByString(ActionInvocation invocation, Result result, String pathinfo) {
        //default values
        String type = defaultResultType;
        String loc = null;
        if (result != null) {
            if (StringUtil.isNotNull(result.type()))
                type = result.type();
            loc = result.location();
        }
        //parse the string "type:location"
        String[] parseRes = parseMatch(pathinfo, type, loc);
        type = parseRes[0];
        loc = parseRes[1];
        //重新封装result参数
        Result res = new DefaultActionInvocation.ResultProxy(match, type, loc);
        return invokeByResult(invocation, res);
    }

    /**
     * "type:location"形式的字符串解析。
     *
     * @param pathinfo "type:location"形式的字符串。
     * @param def type和location的默认值。
     *
     * @return 解析后的{type,location}字符串数组。
     */
    private static String[] parseMatch(String pathinfo, String... def) {
        String type = def[0];
        String loc = def[1];
        //首個非空格非分隔符的位置
        int begin = -1;
        //分隔符前的最后一个非空格字符的位置
        int p1 = -1;
        //分隔符的位置
        int colon = -1;
        int len = pathinfo.length();
        //定位分隔符位置
        for (int i = 0; i < len; i++) {
            char c = pathinfo.charAt(i);
            //may extend
            if (c == ':') {
                colon = i;
                break;
            } else {
                if (c != ' ') {
                    p1 = i;
                    if (begin == -1)
                        begin = i;
                }
            }
        }
        //判断结果类型
        switch (colon) {
            case -1:
                begin = 0;
                p1 = len - 1;
                while (begin < p1 && pathinfo.charAt(begin) == ' ')
                    begin++;
                while (begin < p1 && pathinfo.charAt(p1) == ' ')
                    p1--;
                //非空
                if (begin < p1)
                    type = pathinfo.substring(begin, p1 + 1);
                break;
            case 0:
                break;
            default:
                //非空
                if (begin != -1)
                    type = pathinfo.substring(begin, p1 + 1);
        }
        //分隔符非末位,判断结果路径
        if (colon != -1 && colon != len - 1) {
            //分隔符后的第一个非空格字符的位置
            int p2 = colon + 1;
            //最后一个非空字符的位置
            int end = len - 1;
            while (p2 < end && pathinfo.charAt(p2) == ' ')
                p2++;
            while (p2 < end && pathinfo.charAt(end) == ' ')
                end--;

            if (p2 != end)
                loc = pathinfo.substring(p2, end + 1);
        }
        //返回0.type 1.location形式的数组
        return new String[]{type, loc};
    }

    /**
     * 用于子类继承,提供非字符串对象的处理方式。
     * 默认直接返回非字符串对象。
     *
     * @param invocation Action运行时上下文。
     * @param res Action调用完成后的结果。
     *
     * @return 非字符串对象。
     */
    protected Object invokeObjectResult(ActionInvocation invocation, Object res) {
        return res;
    }

    /**
     * 用于子类继承,提供Action和全局结果对象集合均未匹配情况下的处理方式。
     * 默认直接返回结果字符串。
     *
     * @param invocation Action运行时上下文。
     * @param resInfo Action调用完成后的结果字符串。
     *
     * @return 结果字符串。
     */
    protected Object invokeUndefinedResult(ActionInvocation invocation, String resInfo) {
        //log warn
        LOG.warn("No match Result [{}] at {}", resInfo, invocation.getActionProxy().getMethodInfo());
        //throw new MFinderException("No match Result [" + resInfo + "] at " + ap.getMethodInfo(), ap);
        //不作处理直接跳过,直接返回调用结果字符串
        return resInfo;
    }

    /**
     * 添加Action的路径及代理对象至缓存。
     *
     * @param path Action的路径。
     * @param ace Action的缓存对象。
     */
    protected void putActionCache(String path, ActionCacheEntry ace) {
        if (actionCacheNumber > 0) {
            //如果缓存数据大于设置的条数,则清空缓存
            if (actionCache.size() > actionCacheNumber)
                actionCache.clear();
            actionCache.put(path, ace);
        }
    }

    /**
     * 清除Action的路径映射缓存。
     */
    public void clearActionCache() {
        actionCache.clear();
    }

    @Override
    public void clear() {
        actionCache.clear();
        actions.clear();
        interceptorStacks.clear();
        interceptors.clear();
        resultTypes.clear();
        Injector.clear();
    }
////////////////////////////////////////////////////////////////////////////////

    /**
     * 添加拦截器。
     *
     * @param ip 拦截器代理对象。
     */
    public void addInterceptor(InterceptorProxy ip) {
        String name = ip.getName();

        if (StringUtil.isNull(name))
            throw new IllegalArgumentException("Null name in Interceptor : " + ip.getMethodInfo());

        if (interceptors.containsKey(name)) {
            LOG.warn("Duplicate Interceptor [" + name + "] : "
                    + interceptors.get(name).getMethodInfo() + " to "
                    + ip.getMethodInfo());
        } else {
            LOG.info("Add Interceptor : " + name + " - " + ip.getMethodInfo());
        }
        interceptors.put(name, ip);
    }

    /**
     * 添加拦截器。
     *
     * @param obj 包含{@link Interceptor}注解的类或实例对象。
     *
     * @see mfinder.annotation.Interceptor
     */
    public void addInterceptors(Object obj) {
        boolean isCls = obj instanceof Class;
        Class cls = isCls ? (Class) obj : obj.getClass();
        Object invoker = isCls ? null : obj;
        Method[] ms = cls.getDeclaredMethods();
        for (Method m : ms) {
            int mod = m.getModifiers();
            //带@Interceptor的public/protected方法
            if ((Modifier.isPublic(mod) || Modifier.isProtected(mod))
                    && m.isAnnotationPresent(Interceptor.class)) {
                m.setAccessible(true);
                //static method
                if (Modifier.isStatic(mod)) {
                    addInterceptor(createInterceptorProxy(m, null));
                } else {
                    //为类对象且调用者为 null
                    if (isCls && invoker == null) {
                        invoker = objectFactory.newInstance(cls);
                    }
                    //the same object
                    addInterceptor(createInterceptorProxy(m, invoker));
                }
            }
        }
    }

    /**
     * 添加拦截栈。
     *
     * @param isp 拦截栈代理对象。
     */
    public void addInterceptorStack(InterceptorStackProxy isp) {
        String name = isp.getName();
        if (interceptorStacks.containsKey(name)) {
            LOG.error("Duplicate InterceptorStack : " + name);
        } else {
            LOG.info("Add InterceptorStack : " + name + " - " + isp);
        }
        interceptorStacks.put(name, isp);
    }

    /**
     * 添加拦截栈。
     *
     * @param obj 包含{@link InterceptorStack}注解的类或实例对象。
     *
     * @see mfinder.annotation.InterceptorStack
     */
    public void addInterceptorStacks(Object obj) {
        boolean isCls = obj instanceof Class;
        Class cls = isCls ? (Class) obj : obj.getClass();
        Object invoker = isCls ? null : obj;
        Field[] fs = cls.getDeclaredFields();
        for (Field f : fs) {
            int mod = f.getModifiers();
            //带@InterceptorStack的public属性
            if (Modifier.isPublic(mod) && f.isAnnotationPresent(InterceptorStack.class)) {
                f.setAccessible(true);
                try {
                    //static field
                    if (Modifier.isStatic(mod)) {
                        addInterceptorStack(createInterceptorStackProxy(f, null));
                    } else {
                        //为类对象且调用者为 null
                        if (isCls && invoker == null) {
                            invoker = objectFactory.newInstance(cls);
                        }
                        //the same object
                        addInterceptorStack(createInterceptorStackProxy(f, invoker));
                    }
                } catch (IllegalAccessException e) {
                    throw new MFinderException(e, null);
                }
            }
        }
    }

////////////////////////////////////////////////////////////////////////////////
    /**
     * 添加结果类型。
     *
     * @param rtp 结果类型的代理对象。
     */
    public void addResultType(ResultTypeProxy rtp) {
        String type = rtp.getType();

        if (StringUtil.isNull(type))
            throw new IllegalArgumentException("Null type in ResultType : " + rtp.getMethodInfo());

        if (resultTypes.containsKey(type)) {
            LOG.warn("Duplicate ResultType [" + type + "] : "
                    + resultTypes.get(type).getMethodInfo() + " to "
                    + rtp.getMethodInfo());
        } else {
            LOG.info("Add ResultType : " + type + " - " + rtp.getMethodInfo());
        }
        resultTypes.put(type, rtp);
    }

    /**
     * 添加结果类型。
     *
     * @param obj 包含{@link ResultType}注解的类或实例对象。
     *
     * @see mfinder.annotation.ResultType
     */
    public void addResultTypes(Object obj) {
        boolean isCls = obj instanceof Class;
        Class cls = isCls ? (Class) obj : obj.getClass();
        Object invoker = isCls ? null : obj;
        Method[] ms = cls.getDeclaredMethods();
        for (Method m : ms) {
            int mod = m.getModifiers();
            //带@ResultType的public/protected方法
            if ((Modifier.isPublic(mod) || Modifier.isProtected(mod))
                    && m.isAnnotationPresent(ResultType.class)) {
                m.setAccessible(true);
                //static method
                if (Modifier.isStatic(mod)) {
                    addResultType(createResultTypeProxy(m, null));
                } else {
                    //为类对象且调用者为 null
                    if (isCls && invoker == null) {
                        invoker = objectFactory.newInstance(cls);
                    }
                    //the same object
                    addResultType(createResultTypeProxy(m, invoker));
                }
            }
        }
    }

    /**
     * 添加结果对象。
     *
     * @param rp 结果对象的代理对象。
     */
    public void addResult(ResultProxy rp) {
        String name = rp.getResult().name();
        if (results.containsKey(name)) {
            LOG.warn("Duplicate Result [" + name + "] : "
                    + results.get(name).getMethodInfo() + " to "
                    + rp.getMethodInfo());
        } else {
            LOG.info("Add Result : " + name + " - " + rp.getMethodInfo());
        }
        results.put(name, rp);
    }

    /**
     * 添加全局结果对象。
     *
     * @param obj 包含{@link Result}注解的类或实例对象。
     *
     * @see mfinder.annotation.Result
     */
    public void addResults(Object obj) {
        boolean isCls = obj instanceof Class;
        Class cls = isCls ? (Class) obj : obj.getClass();
        Object invoker = isCls ? null : obj;
        Method[] ms = cls.getDeclaredMethods();
        for (Method m : ms) {
            int mod = m.getModifiers();
            //带@Result的public/protected方法
            if ((Modifier.isPublic(mod) || Modifier.isProtected(mod))
                    && m.isAnnotationPresent(Result.class)) {
                m.setAccessible(true);
                //static method
                if (Modifier.isStatic(mod)) {
                    addResult(createResultProxy(m, null));
                } else {
                    //为类对象且调用者为 null
                    if (isCls && invoker == null) {
                        invoker = objectFactory.newInstance(cls);
                    }
                    //the same object
                    addResult(createResultProxy(m, invoker));
                }
            }
        }
    }
////////////////////////////////////////////////////////////////////////////////

    /**
     * 添加Action。
     *
     * @param ap Action代理对象。
     */
    public void addAction(ActionProxy ap) {
        String aPath = ap.getPath();

        if (StringUtil.isNull(aPath))
            throw new IllegalArgumentException("Null path in Action : " + ap.getMethodInfo());

        ActionProxy exist = actions.get(aPath);
        if (exist != null) {
            LOG.warn("Duplicate Action [" + aPath + "] : "
                    + exist.getMethodInfo() + " to "
                    + ap.getMethodInfo());
        } else {
            LOG.info("Add Action : " + aPath + " - " + ap.getMethodInfo());
        }
        actions.put(aPath, ap);
    }

    /**
     * 添加Action。
     *
     * @param obj 包含{@link Action}注解的类或实例对象。
     *
     * @see mfinder.annotation.Action
     */
    public void addActions(Object obj) {
        //判断传入参数为类或实例对象
        boolean isCls = obj instanceof Class;
        Class cls = isCls ? (Class) obj : obj.getClass();
        Object invoker = isCls ? null : obj;
        Method[] ms = cls.getDeclaredMethods();
        for (Method m : ms) {
            int mod = m.getModifiers();
            //带@Action的public/protected方法
            if ((Modifier.isPublic(mod) || Modifier.isProtected(mod))
                    && m.isAnnotationPresent(Action.class)) {
                m.setAccessible(true);
                try {
                    //static method
                    if (Modifier.isStatic(mod)) {
                        addAction(createActionProxy(m, null));
                    } else {
                        if (isCls && invoker == null) {
                            invoker = objectFactory.newInstance(cls);
                        }
                        //the same object
                        addAction(createActionProxy(m, invoker));
                    }
                } catch (IllegalAccessException e) {
                    throw new MFinderException(e, null);
                } catch (InvocationTargetException e) {
                    throw new MFinderException(e, null);
                }
            }
        }
    }

////////////////////////////////////////////////////////////////////////////////
    /**
     * 创建Interceptor代理对象。
     *
     * @param method 指定的方法。
     * @param obj 方法所在的对象。
     *
     * @return Interceptor代理对象。
     */
    private InterceptorProxy createInterceptorProxy(Method method, Object obj) {
        Interceptor interceptor = method.getAnnotation(Interceptor.class);
        Class[] params = method.getParameterTypes();

        //check interceptor invoke args
        boolean requireAction = false;
        //interceptor代理的方法无参数或参数仅为ActionInvocation或其子类
        if (params.length == 0) {
            requireAction = false;
        } //未指定actionInvocationClass参数类型时允许ActionInvocation任意子类;否则为actionInvocationClass的父类
        else if (isProxyMethod(params)) {
            requireAction = true;
        } else {
            throw new IllegalArgumentException("Illegal arguments in Interceptor : " + method);
        }
        return new InterceptorProxy(interceptor.name().trim(), method, obj, requireAction);
    }

    /**
     * 创建InterceptorStack代理对象
     *
     * @param field 指定的字段。
     * @param obj 字段所在对象。
     *
     * @return InterceptorStack代理对象。
     *
     * @throws IllegalAccessException 如果调用的对象无法访问指定字段。
     */
    private InterceptorStackProxy createInterceptorStackProxy(Field field, Object obj) throws
            IllegalAccessException {
        InterceptorStack interceptorStack = field.getAnnotation(InterceptorStack.class);
        String name = interceptorStack.name().trim();

        //interceptorStack name
        //未指定拦截栈名称则取字符串的值为名称
        if (StringUtil.isNull(name)) {
            name = field.get(obj).toString();
            //空命名异常
            if (StringUtil.isNull(name))
                throw new IllegalArgumentException("Null name in InterceptorStack : "
                        + field.getName() + " at " + obj.getClass());
        }
        //interceptors name
        String[] names = interceptorStack.interceptors();

        List<InterceptorProxy> list = null;
        if (names != null) {
            list = new ArrayList<InterceptorProxy>(names.length);
            //add interceptorStack
            //for (int i = names.length - 1; i >= 0; i--) {
            for (int i = 0; i < names.length; i++) {
                InterceptorProxy ip = interceptors.get(names[i]);
                //if null
                if (ip == null) {
                    LOG.warn("No such Interceptor : " + names[i]);
                } else {
                    list.add(ip);
                }
            }
        }
        return new InterceptorStackProxy(name, field, list);
    }

    /**
     * 创建ResultType代理对象。
     *
     * @param method 指定的方法。
     * @param obj 方法所在的对象。
     *
     * @return ResultType代理对象。
     */
    private ResultTypeProxy createResultTypeProxy(Method method, Object obj) {
        ResultType type = method.getAnnotation(ResultType.class);
        Class[] params = method.getParameterTypes();

        boolean requireAction = false;
        //ResultType代理的方法无参数或参数仅为ActionInvocation或其子类
        if (params.length == 0) {
            requireAction = false;
        } else if (isProxyMethod(params)) {
            requireAction = true;
        } else {
            throw new IllegalArgumentException("Illegal arguments in ResultType : " + method);
        }

        return new ResultTypeProxy(type.type().trim(), method, obj, requireAction);
    }

    /**
     * 创建Result代理对象。
     *
     * @param method 指定的方法。
     * @param obj 方法所在的对象。
     *
     * @return Result代理对象
     */
    private ResultProxy createResultProxy(Method method, Object obj) {
        Result res = method.getAnnotation(Result.class);
        Class[] params = method.getParameterTypes();

        boolean requireAction = false;
        //ResultType代理的方法无参数或参数仅为ActionInvocation或其子类
        if (params.length == 0) {
            requireAction = false;
        } else if (isProxyMethod(params)) {
            requireAction = true;
        } else {
            throw new IllegalArgumentException("Illegal arguments in Result : " + method);
        }
        return new ResultProxy(res, method, obj, requireAction);
    }

    /**
     * 判断代理方法的参数是否合法;仅允许无参数方法或仅ActionInvocation类型参数的方法。
     * 未指定参数类型时允许ActionInvocation类型的任意子类;否则为{@link #actionInvocationClass}的父类。
     *
     * @param params 代理方法的参数类型。
     *
     * @return 所代理的方法合法返回true,否则为false。
     */
    private boolean isProxyMethod(Class[] params) {
        if (params.length > 1)
            return false;
        return params.length == 0 ? true : actionInvocationClass == null
                ? ActionInvocation.class.isAssignableFrom(params[0])
                : params[0].isAssignableFrom(actionInvocationClass);
    }

    /**
     * 创建Action代理对象。
     *
     * @param method 指定的方法。
     * @param obj 方法所在的对象。
     *
     * @return Action代理对象。
     */
    private ActionProxy createActionProxy(Method method, Object obj) throws IllegalAccessException,
            InvocationTargetException {
        Namespace ns = method.getDeclaringClass().getAnnotation(Namespace.class);
        //trim empay and '/'
        String namespace = ns == null ? PATH_SEPARATOR + "" : PATH_SEPARATOR + StringUtil.trim(ns.name(), PATH_SEPARATOR);

        String path = null;
        //not nullable Action
        Action action = method.getAnnotation(Action.class);
        //Action名称可能为空字符串
        String aname = action.name().trim();
        if ("".equals(aname)) {
            //Action名称为空字符串时取其方法的名称(区分大小写)
            aname = method.getName();
            //if namespace is '/' or not
            path = namespace.length() == 1 ? PATH_SEPARATOR + aname : namespace + PATH_SEPARATOR + aname;
        } else {
            //action's name can't be null by annotation
            String name = StringUtil.trim(aname, PATH_SEPARATOR);
            //if action's name is trim as empty
            if (name.isEmpty()) {
                path = namespace;
            } else if (PATH_SEPARATOR == aname.charAt(0)) {
                path = PATH_SEPARATOR + name;
            } else {
                //if namespace is '/' or not
                path = namespace.length() == 1 ? PATH_SEPARATOR + name : namespace + PATH_SEPARATOR + name;
            }
        }

        //包含特别属性注入的Action需重新生成对象
        if (obj != null && Injector.actionInjection.containsKey(path)) {
            obj = objectFactory.newInstance(obj.getClass());
            Injector.injectAction(path, obj);
        }

        //Action中不记录路径的后缀名称
        ActionProxy ap = new ActionProxy(this, namespace, path, action, method, obj);

        //interceptorStack
        String stackName = action.interceptorStack().trim();
        //not not nullable action's interceptors
        String[] interceptorNames = action.interceptors();

        List<InterceptorProxy> inters = new ArrayList<InterceptorProxy>();
        //action interceptors
        if (interceptorNames.length != 0) {
            ////action interceptorStack
            if (StringUtil.isNotNull(stackName)) {
                addActionInterceptors(inters, stackName, ap);
            }
            //action中申明的interceptors
            for (String name : action.interceptors()) {
                InterceptorProxy ip = interceptors.get(name);
                if (ip == null) {
                    LOG.warn("No such Interceptor [" + name + "] defined in : " + ap.getMethodInfo());
                } else {
                    inters.add(ip);
                }
            }
        } //action interceptorStack
        else if (StringUtil.isNotNull(stackName)) {
            addActionInterceptors(inters, stackName, ap);
        } else {
            //是否已设置action的拦截器集合
            boolean setInterceptors = false;
            //namespace interceptorStack & interceptors
            if (ns != null) {
                //namespace interceptorStack
                if (StringUtil.isNotNull(stackName = ns.interceptorStack().trim())) {
                    setInterceptors = true;
                    addActionInterceptors(inters, stackName, ap);
                }
                //namespace interceptors
                if (ns.interceptors().length != 0) {
                    setInterceptors = true;
                    for (String name : ns.interceptors()) {
                        InterceptorProxy ip = interceptors.get(name);
                        if (ip == null) {
                            LOG.warn("No such Interceptor [" + name + "] defined in : " + ap.getMethodInfo());
                        } else {
                            inters.add(ip);
                        }
                    }
                }
            }
            //defaultInterceptorStack
            if (!setInterceptors) {
                if (StringUtil.isNotNull(stackName = defaultInterceptorStack)) {
                    addActionInterceptors(inters, stackName, ap);
                }
            }
        }
        //trim
        ((ArrayList) inters).trimToSize();
        ap.setInterceptors(inters);

        //set results
        Result[] rs = action.results();
        Map<String, Result> res = new HashMap<String, Result>(rs.length);
        for (Result r : rs) {
            res.put(r.name(), r);
        }
        ap.setResults(res);

        return ap;
    }

    /**
     * 由指定拦截栈名称添加拦截器至Action的拦截器集合。
     *
     * @param interceptors Action的拦截器集合。
     * @param stackName 指定的拦截栈名称。
     * @param ap Action代理对象。
     */
    private void addActionInterceptors(List<InterceptorProxy> interceptors, String stackName,
            ActionProxy ap) {
        InterceptorStackProxy isp = interceptorStacks.get(stackName);
        if (isp == null) {
            LOG.warn("No such InterceptorStack [" + stackName + "] defined in : " + ap.getMethodInfo());
        } else {
            if (isp.getInterceptors() != null)
                interceptors.addAll(isp.getInterceptors());
        }
    }
////////////////////////////////////////////////////////////////////////////////

    @Override
    public Map<String, ActionProxy> getActions() {
        return actions;
    }

    /**
     * 返回缓存的Action路径与其代理对象的映射。
     *
     * @return 缓存的Action路径与其代理对象的映射。
     */
    public Map<String, ActionCacheEntry> getActionCache() {
        return actionCache;
    }

    @Override
    public Map<String, InterceptorProxy> getInterceptors() {
        return interceptors;
    }

    @Override
    public Map<String, InterceptorStackProxy> getInterceptorStacks() {
        return interceptorStacks;
    }

    @Override
    public Map<String, ResultTypeProxy> getResultTypes() {
        return resultTypes;
    }

    @Override
    public String getDefaultInterceptorStack() {
        return defaultInterceptorStack;
    }

    /**
     * 设置默认拦截栈名称。
     * 更改默认拦截栈名称对已存在的拦截栈{@link #interceptorStacks}无影响。
     * 更改默认拦截栈名称对已存在的{@link #actions}无影响。
     *
     * @param defaultInterceptorStack 默认拦截栈名称。
     */
    public void setDefaultInterceptorStack(String defaultInterceptorStack) {
        LOG.info("setDefaultInterceptorStack : " + defaultInterceptorStack);
        this.defaultInterceptorStack = defaultInterceptorStack;
    }

    @Override
    public String getDefaultResultType() {
        return defaultResultType;
    }

    /**
     * 设置默认结果视图类型。
     * 更改默认结果视图类型会影响已存在的{@link #actions}的结果调用。
     * 如果已有的Action调用结束后使用了默认视图类型,则会被影响。
     *
     * @param defaultResultType 默认视图类型。
     */
    public void setDefaultResultType(String defaultResultType) {
        LOG.info("setDefaultResultType : " + defaultResultType);
        this.defaultResultType = defaultResultType;
    }

    /**
     * 返回全局结果对象集合。
     *
     * @return 全局结果对象集合。
     */
    @Override
    public Map<String, ResultProxy> getResults() {
        return results;
    }

    /**
     * 返回路径后缀分隔符。
     *
     * @return 路径后缀分隔符名称。
     */
    public String getExtension() {
        return extension;
    }

    /**
     * 路径后缀名称。
     * 当后缀为单个字符时,按路径最后出现分割符的位置截断路径后缀;
     * 当后缀为未空字符串时,如果路径已后缀结尾,截断后缀。
     * 更改路径后缀名称对已存在的{@link #actions}无影响。
     *
     * @param extension 路径后缀名称。
     *
     * @see #invokeAction(java.lang.String, java.lang.Object[])
     */
    public void setExtension(String extension) {
        if (extension == null)
            return;
        this.extension = extension.trim();
        LOG.info("setExtension : " + this.extension);
    }

    /**
     * Action运行时上下文的类型。
     *
     * @return Action运行时上下文的类型。
     */
    public Class<? extends ActionInvocation> getActionInvocationClass() {
        return actionInvocationClass;
    }

    /**
     * 设置Action运行时上下文的类型。
     *
     * @param actionInvocationClass Action运行时上下文的类型。
     */
    public void setActionInvocationClass(Class<? extends ActionInvocation> actionInvocationClass) {
        this.actionInvocationClass = actionInvocationClass;
        LOG.info("setActionInvocationClass : " + this.actionInvocationClass);
    }

    /**
     * 返回{@link #getActionCache()}的最大缓存数目。
     *
     * @return {@link #getActionCache()}的最大缓存数目。
     */
    public int getActionCacheNumber() {
        return actionCacheNumber;
    }

    /**
     * 设置{@link #getActionCache()}的最大缓存数目。
     *
     * @param actionCacheNumber {@link #getActionCache()}的最大缓存数目。
     */
    public void setActionCacheNumber(int actionCacheNumber) {
        this.actionCacheNumber = actionCacheNumber;
        LOG.info("setActionCacheNumber : " + this.actionCacheNumber);
    }

    /**
     * 设置创建对象的工厂对象。
     *
     * @param objectFactory 创建对象的工厂对象。
     */
    public void setObjectFactory(ObjectFactory objectFactory) {
        this.objectFactory = objectFactory;
        LOG.info("setObjectFactory : " + this.objectFactory);
    }

    @Override
    public ObjectFactory getObjectFactory() {
        return objectFactory;
    }

    /**
     * 缓存对象。
     */
    public static class ActionCacheEntry {

        /** Action的代理对象 */
        ActionProxy actionProxy;

        /** Actino路径的参数匹配映射,如果没有则为 null */
        Map<String, String> matchParameters;

        /**
         * 构造一个无属性的缓存对象。
         */
        public ActionCacheEntry() {
        }

        /**
         * 构造一个指定Action的代理对象和Actino路径的参数匹配映射的缓存对象。
         *
         * @param actionProxy Action的代理对象。
         * @param matchParameters Actino路径的参数匹配映射。
         */
        public ActionCacheEntry(ActionProxy actionProxy, Map<String, String> matchParameters) {
            this.actionProxy = actionProxy;
            this.matchParameters = matchParameters;
        }
    }
}
TOP

Related Classes of mfinder.impl.DefaultActionFactory$ActionCacheEntry

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.