package org.nutz.lang;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.nutz.lang.util.Regex;

/**
 * 关于数的一些帮助函数
 *
 * @author zozoh(zozohtnt@gmail.com)
 */
public abstract class Nums {

    /**
     * @param a
     *            数字
     * @param b
     *            数字
     * @return 两个数的最大公约数 greatest common divisor(gcd)
     */
    public static int gcd(int a, int b) {
        a = Math.round(a);
        b = Math.round(b);
        if (b != 0) {
            return gcd(b, a % b);
        }
        return a;
    }

    /**
     * @param list
     *            一组整数
     * @return 一组整数的最大公约数 greatest common divisor(gcd)
     */
    public static int gcds(int... list) {
        // 没数
        if (list.length == 0)
            return Integer.MIN_VALUE;
        // 一个是自己
        if (list.length == 1) {
            return list[0];
        }
        // 两个以上
        int gcd = gcd(list[0], list[1]);
        for (int i = 2; i < list.length; i++) {
            gcd = gcd(gcd, list[i]);
        }
        // 返回
        return gcd;
    }

    /**
     * @param a
     *            数字
     * @param b
     *            数字
     * @return 两个数的最小公倍数 lowest common multiple (LCM)
     */
    public static int lcm(int a, int b) {
        a = Math.round(a);
        b = Math.round(b);
        return a * b / gcd(a, b);
    }

    /**
     * @param list
     *            一组整数
     * @return 一组整数的最小公倍数 lowest common multiple (LCM)
     */
    public static int lcms(int... list) {
        // 没数
        if (list.length == 0)
            return Integer.MAX_VALUE;
        // 一个是自己
        if (list.length == 1) {
            return list[0];
        }
        // 两个以上
        int lcm = lcm(list[0], list[1]);
        for (int i = 2; i < list.length; i++) {
            lcm = lcm(lcm, list[i]);
        }
        // 返回
        return lcm;
    }

    /**
     * 计算尺寸
     *
     * @param v
     *            要计算的尺寸值的类型可以是
     *

     *
500 - 整数，直接返回
     *
.12 - 浮点，相当于一个百分比，可以大于 1.0
     *
"12%" - 百分比，相当于 .12
     *

     * @param base
     *            百分比的基数
     *
     * @return 根据基数计算后的数值
     */
    public static double dimension(String v, double base) {
        // 试试整型
        try {
            Integer nb = Integer.valueOf(v);
            return nb.intValue();
        }
        catch (NumberFormatException e) {}

        // 试试浮点
        try {
            Double nb = Double.valueOf(v);
            return nb.doubleValue() * base;
        }
        catch (NumberFormatException e) {}

        // 百分比
        Pattern p = Regex.getPattern("^([0-9.]{1,})%$");
        Matcher m = p.matcher(v);
        if (m.find()) {
            Double nb = Double.valueOf(m.group(1));
            return (nb.doubleValue() / 100) * base;
        }
        // 靠不知道是啥
        throw Lang.makeThrow("fail to dimension : " + v);
    }

    /**
     * @see #dimension(String, double)
     */
    public static int dimension(String v, int base) {
        return (int) (dimension(v, (double) base));
    }

    /**
     * @param nbs
     *            一组数字
     * @return 数字之和
     */
    public static int sum(int... nbs) {
        int re = 0;
        for (int nb : nbs)
            re += nb;
        return re;
    }

    /**
     * 一个数的字面量的进制和值
     */
    public static class Radix {
        Radix(String val, int radix) {
            this.val = val;
            this.radix = radix;
        }

        public int radix;
        public String val;
    }

    /**
     * @param str
     *            数字的字符串
     * @return 字符串的进制
     *
     * @see org.nutz.lang.Nums.Radix
     */
    public static Radix evalRadix(String str) {
        if (str.startsWith("0x"))
            return new Radix(str.substring(2), 16);
        if (str.startsWith("0") && str.length() > 1)
            return new Radix(str.substring(1), 8);
        if (str.startsWith("0b"))
            return new Radix(str.substring(2), 2);
        return new Radix(str, 10);
    }

    /**
     * 将一个字符串变成一个整型数组，如果字符串不符合规则，对应的元素为 -1

     * 比如：
     *
     *

     * "3,4,9"   =>  [  3, 4, 9 ]
     * "a,9,100" =>  [ -1, 9, 100 ]
     *

     *
     * @param str
     *            半角逗号分隔的数字字符串
     * @return 数组
     */
    public static int[] splitInt(String str) {
        String[] ss = Strings.splitIgnoreBlank(str);
        if (null == ss)
            return null;
        int[] ns = new int[ss.length];
        for (int i = 0; i < ns.length; i++) {
            try {
                ns[i] = Integer.parseInt(ss[i]);
            }
            catch (NumberFormatException e) {
                ns[i] = -1;
            }
        }
        return ns;
    }

    /**
     * @see #splitInt(String)
     */
    public static long[] splitLong(String str) {
        String[] ss = Strings.splitIgnoreBlank(str);
        if (null == ss)
            return null;
        long[] ns = new long[ss.length];
        for (int i = 0; i < ns.length; i++) {
            try {
                ns[i] = Long.parseLong(ss[i]);
            }
            catch (NumberFormatException e) {
                ns[i] = -1;
            }
        }
        return ns;
    }

    /**
     * 将一个字符串变成一个浮点数数组，如果字符串不符合规则，对应的元素为 0.0

     * 比如：
     *
     *

     * "3,4,9"     =>  [ 3.0f, 4.0f, 9.0f ]
     * "a,9.8,100" =>  [ 0.0f, 9.0f, 100.0f ]
     *

     *
     * @param str
     *            半角逗号分隔的数字字符串
     * @return 数组
     */
    public static float[] splitFloat(String str) {
        String[] ss = Strings.splitIgnoreBlank(str);
        if (null == ss)
            return null;
        float[] ns = new float[ss.length];
        for (int i = 0; i < ns.length; i++) {
            try {
                ns[i] = Float.parseFloat(ss[i]);
            }
            catch (NumberFormatException e) {
                ns[i] = 0.0f;
            }
        }
        return ns;
    }

    /**
     * 将一个字符串变成一个双精度数数组，如果字符串不符合规则，对应的元素为 -1
     *
     * @param str
     *            半角逗号分隔的数字字符串
     * @return 数组
     */
    public static double[] splitDouble(String str) {
        String[] ss = Strings.splitIgnoreBlank(str);
        if (null == ss)
            return null;
        double[] ns = new double[ss.length];
        for (int i = 0; i < ns.length; i++) {
            try {
                ns[i] = Long.parseLong(ss[i]);
            }
            catch (NumberFormatException e) {
                ns[i] = -1;
            }
        }
        return ns;
    }

    /**
     * @see #splitInt(String)
     */
    public static boolean[] splitBoolean(String str) {
        String[] ss = Strings.splitIgnoreBlank(str);
        if (null == ss)
            return null;
        boolean[] ns = new boolean[ss.length];
        for (int i = 0; i < ns.length; i++) {
            try {
                ns[i] = Regex.match("^(1|yes|true|on)$", ss[i].toLowerCase());
            }
            catch (NumberFormatException e) {
                ns[i] = false;
            }
        }
        return ns;
    }

    /**
     * @see #indexOf(int[], int, int)
     */
    public static int indexOf(int[] arr, int v) {
        return indexOf(arr, v, 0);
    }

    /**
     * @param arr
     *            数组
     * @param v
     *            值
     * @param off
     *            从那个下标开始搜索(包含)
     * @return 第一个匹配元素的下标
     */
    public static int indexOf(int[] arr, int v, int off) {
        if (null != arr)
            for (int i = off; i < arr.length; i++) {
                if (arr[i] == v)
                    return i;
            }
        return -1;
    }

    /**
     * @param arr
     * @param v
     * @return 最后一个匹配元素的下标
     */
    public static int lastIndexOf(int[] arr, int v) {
        if (null != arr)
            for (int i = arr.length - 1; i >= 0; i--) {
                if (arr[i] == v)
                    return i;
            }
        return -1;
    }

    /**
     * @see #indexOf(char[], char, int)
     */
    public static int indexOf(char[] arr, char v) {
        if (null != arr)
            for (int i = 0; i < arr.length; i++) {
                if (arr[i] == v)
                    return i;
            }
        return -1;
    }

    /**
     * @param arr
     *            数组
     * @param v
     *            值
     * @param off
     *            从那个下标开始搜索(包含)
     * @return 第一个匹配元素的下标
     */
    public static int indexOf(char[] arr, char v, int off) {
        if (null != arr)
            for (int i = off; i < arr.length; i++) {
                if (arr[i] == v)
                    return i;
            }
        return -1;
    }

    /**
     * @param arr
     * @param v
     * @return 第一个匹配元素的下标
     */
    public static int lastIndexOf(char[] arr, char v) {
        if (null != arr)
            for (int i = arr.length - 1; i >= 0; i--) {
                if (arr[i] == v)
                    return i;
            }
        return -1;
    }

    /**
     * @see #indexOf(long[], long, int)
     */
    public static int indexOf(long[] arr, long v) {
        return indexOf(arr, v, 0);
    }

    /**
     * @param arr
     *            数组
     * @param v
     *            值
     * @param off
     *            从那个下标开始搜索(包含)
     * @return 第一个匹配元素的下标
     */
    public static int indexOf(long[] arr, long v, int off) {
        if (null != arr)
            for (int i = off; i < arr.length; i++) {
                if (arr[i] == v)
                    return i;
            }
        return -1;
    }

    /**
     * @param arr
     * @param v
     * @return 第一个匹配元素的下标
     */
    public static int lastIndexOf(long[] arr, long v) {
        if (null != arr)
            for (int i = arr.length - 1; i >= 0; i--) {
                if (arr[i] == v)
                    return i;
            }
        return -1;
    }

    /**
     * 不解释，你懂的
     */
    public static int[] array(int... is) {
        return is;
    }

    /**
     * 判断一个整数是否在数组中
     *
     * @param arr
     *            数组
     * @param i
     *            整数
     * @return 是否存在
     */
    public static boolean isin(int[] arr, int i) {
        return indexOf(arr, i) >= 0;
    }

    /**
     * 整合两个整数数组为一个数组 这个方法在JDK5不可用!!
     *
     * @param arr
     *            整数数组
     * @param is
     *            变参
     * @return 新的整合过的数组
     */
    public static int[] join(int[] arr, int... is) {
        if (null == arr)
            return is;
        int length = arr.length + is.length;
        int[] re = new int[length];
        System.arraycopy(arr, 0, re, 0, arr.length);
        int i = arr.length;
        for (int num : is)
            re[i++] = num;
        return re;
    }

    /**
     * 不解释，你懂的
     */
    public static long[] arrayL(long... is) {
        return is;
    }

    /**
     * 判断一个长整数是否在数组中
     *
     * @param arr
     *            数组
     * @param i
     *            长整数
     * @return 是否存在
     */
    public static boolean isin(long[] arr, long i) {
        return indexOf(arr, i) >= 0;
    }

    /**
     * 整合两个长整数数组为一个数组 这个方法在JDK5不可用!!
     *
     * @param arr
     *            长整数数组
     * @param is
     *            变参
     * @return 新的整合过的数组
     */
    public static long[] join(long[] arr, long... is) {
        if (null == arr)
            return is;
        int length = arr.length + is.length;
        long[] re = new long[length];
        System.arraycopy(arr, 0, re, 0, arr.length);
        int i = arr.length;
        for (long num : is)
            re[i++] = num;
        return re;
    }

    /**
     * 不解释，你懂的
     */
    public static char[] arrayC(char... is) {
        return is;
    }

    /**
     * 判断一个长整数是否在数组中
     *
     * @param arr
     *            数组
     * @param i
     *            长整数
     * @return 是否存在
     */
    public static boolean isin(char[] arr, char i) {
        return indexOf(arr, i) >= 0;
    }

    /**
     * 整合两个长整数数组为一个数组 这个方法在JDK5不可用!!
     *
     * @param arr
     *            长整数数组
     * @param is
     *            变参
     * @return 新的整合过的数组
     */
    public static char[] join(char[] arr, char... is) {
        if (null == arr)
            return is;
        int length = arr.length + is.length;
        char[] re = new char[length];
        System.arraycopy(arr, 0, re, 0, arr.length);
        int i = arr.length;
        for (char num : is)
            re[i++] = num;
        return re;
    }
}


package org.nutz.dao.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import javax.sql.DataSource;

import org.nutz.dao.Dao;
import org.nutz.dao.impl.NutDao;
import org.nutz.dao.impl.SimpleDataSource;
import org.nutz.lang.Files;
import org.nutz.lang.Lang;
import org.nutz.lang.Mirror;
import org.nutz.lang.Streams;
import org.nutz.log.Log;
import org.nutz.log.Logs;

/**
 * 为非Mvc,Ioc环境下的程序提供辅助支持.

 * DaoUp不是一次性产品!! 如果新建DaoUp然后立马抛弃掉, 从中获取的NutDao/DataSource将会关闭!!

 * 请注意使用场景!!! 在Mvc下有IocBy的情况下,不需要也不应该使用本类!!

 * Mvc下可以通过 Mvcs.getIoc()或Mvcs.ctx().getDefaultIoc()获取Ioc容器,从而获取其中的Dao实例!!

 * Mvc应尽量使用注入,而非主动取Dao实例,更不应该主动new NutDao!!!
 *
 最基本的用法

    DaoUp.me().init(new File("db.properties"));
    Dao dao = DaoUp.me().dao();

    dao.insert(.......);

    // 注意,不是每次用完Dao就关,是整个程序关闭的时候才关!!
    // 程序结束前关闭相关资源.
    DaoUp.me().close();

请参阅test源码中的DaoUpTest获取Dao的入门技巧.
 *
 * @author wendal(wendal1985@gmail.com)
 *
 */
public class DaoUp {

    /**
     * 日志对象
     */
    private static final Log log = Logs.get();

    /**
     * 内置单例
     */
    protected static DaoUp me = new DaoUp("_defult_");

    /**
     * Druid数据源的工厂方法类
     */
    protected static Class<?> druidFactoryClass;

    /**
     * 如果本对象被GC,是否触发自动关闭
     */
    protected boolean autoCloseWhenFinalize = true;

    static {
        try {
            /**
             * 加载DruidDataSourceFactory, 即Druid连接池的工厂类
             */
            druidFactoryClass = Lang.loadClass("com.alibaba.druid.pool.DruidDataSourceFactory");
        }
        catch (ClassNotFoundException e) {
            // 找不到就用内置的SimpleDataSource好了.
            // TODO 支持其他类型的数据源, 低优先级
        }
    }

    /**
     * 获取内置的DaoUp单例
     * @return DaoUp实例
     */
    public static DaoUp me() {
        return me;
    }

    /**
     * 需要新建多个DaoUp,请继承DaoUp,从而暴露构造方法或使用工厂方法!!
     */
    protected DaoUp(String name) {
        this.name = name;
    }

    /**
     * Dao对象
     */
    protected Dao dao;

    /**
     * 连接池
     */
    protected DataSource dataSource;

    /**
     * 当前DaoUp的名称
     */
    protected String name;

    /**
     * 返回所持有的Dao实例,如果DaoUp还没初始化或已经关闭,这里会返回null
     * @return Dao实例
     */
    public Dao dao() {
        return dao;
    }

    /**
     * 获取数据源, 如果DaoUp还没初始化或已经关闭,这里会返回null
     * @return 数据源(连接池)
     */
    public DataSource getDataSource() {
        return dataSource;
    }

    /**
     * 主动设置数据源(连接池)
     * @param dataSource 数据源(连接池)
     */
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
        setDao(new NutDao(dataSource));
    }

    /**
     * 主动设置Dao实例
     * @param dao Dao实例
     */
    public void setDao(Dao dao) {
        if (this.dao != null)
            log.infof("override old Dao=%s by new Dao=%s", this.dao, dao);
        this.dao = dao;
    }

    /**
     * 从classpath或当前目录下查找配置文件来进行初始化
     * @param name
     */
    public void init(String name) throws IOException {
        init(new FileInputStream(Files.findFile(name)));
    }

    /**
     * 从一个文件读取数据库配置
     * @param f 配置文件
     * @throws IOException 文件不可读取时抛出异常
     */
    public void init(File f) throws IOException {
        init(new FileInputStream(f));
    }

    /**
     * 从一个流读取数据库配置
     * @param in 输入流,包含配置信息
     * @throws IOException 读取失败是抛出异常
     */
    public void init(InputStream in) throws IOException {
        Properties props = new Properties();
        try {
            props.load(in);
            init(props);
        }
        finally {
            Streams.safeClose(in);
        }
    }

    /**
     * 给定一个Properties配置,不能为null!!!! 最起码要包含一个叫url的参数!!!
     * @param props 配置信息
     */
    public void init(Properties props) {
        if (dao != null) {
            throw new IllegalArgumentException("DaoUp is inited!!");
        }
        if (props.size() == 0) {
            throw new IllegalArgumentException("DaoUp props size=0!!!");
        }
        DataSource ds = buildDataSource(props);
        setDataSource(ds);
    }

    /**
     * 构建DataSource,子类可覆盖. 如果存在Druid,则使用之,否则使用内置的SimpleDataSource
     * @param props 配置信息
     * @return 目标DataSource
     */
    protected DataSource buildDataSource(Properties props) {
        if (druidFactoryClass != null) {
            log.debug("build DruidDataSource by props");
            Mirror<?> mirror = Mirror.me(druidFactoryClass);
            DataSource ds = (DataSource) mirror.invoke(null, "createDataSource", props);
            if (!props.containsKey("maxWait"))
                Mirror.me(ds).setValue(ds, "maxWait", 15*1000);
            return ds;
        }
        log.debug("build SimpleteDataSource by props");
        return SimpleDataSource.createDataSource(props);
    }

    /**
     * 关闭本DaoUp,将关闭DataSource并将dao和dataSource置为null!!!

     * 只能在程序关闭时调用,严禁在每次Dao操作后调用!!
     */
    public synchronized void close() {
        if (dao == null)
            return;
        log.infof("shutdown DaoUp(name=%s)", name);
        try {
            Mirror.me(dataSource).invoke(dataSource, "close");
        }
        catch (Throwable e) {
        }
        this.dataSource = null;
        this.dao = null;
    }

    /**
     * 设置是否在本对象被GC时自动关闭相关资源.

     * 若要设置为false, 请慎重考虑,因为绝大部分情况下设置为true并不能解决您当前遇到的问题!!

     * DaoUp类不是设计为即用即抛的!!!而是设计为单例模式的!!!!!!!

     * 如果是遇到DataSource is closed之类的异常, 在考虑使用本配置前请先检讨代码!!!

     * @param autoCloseWhenFinalize 是否自动关闭资源
     */
    public void setAutoCloseWhenFinalize(boolean autoCloseWhenFinalize) {
        this.autoCloseWhenFinalize = autoCloseWhenFinalize;
        if (!autoCloseWhenFinalize) {
            log.warnf("DaoUp[%s] autoCloseWhenFinalize is disabled. You had been WARN!!", name);
        }
    }

    /**
     * 如果被GC,主动触发关闭,除非autoCloseWhenFinalize为false
     */
    protected void finalize() throws Throwable {
        if (autoCloseWhenFinalize)
            close();
        super.finalize();
    }

//    /**
//     * 提供一个配置对象,然后生成Dao实例

//     *
应该把对象
//     * 返回的对象!!
//     * @param conf 可以为DataSource/File/InputStream/Properties/String
//     * @return 初始化好的Dao实例
//     * @throws IOException 读取文件出错时抛出
//     */
//    public static Dao factory(Object conf) throws IOException {
//        if (conf == null)
//            return null;
//        if (conf instanceof Dao)
//            return (Dao) conf;
//        if (conf instanceof DataSource)
//            return new NutDao((DataSource)conf);
//        DaoUp up = new DaoUp("daoup_factory_" + System.currentTimeMillis());
//        if (conf instanceof File) {
//            up.init((File)conf);
//        } else if (conf instanceof InputStream) {
//            up.init((InputStream)conf);
//        } else if (conf instanceof Properties) {
//            up.init((Properties)conf);
//        } else {
//            up.init(conf.toString());
//        }
//        Dao dao = up.dao();
//        up.autoCloseWhenFinalize = false;
//        return dao;
//    }

    // TODO 完成一个repl
//    public static void main(String[] args) {
//
//    }
}


package org.nutz.mvc.view;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.nutz.el.El;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.segment.CharSegment;
import org.nutz.lang.segment.Segment;
import org.nutz.lang.util.Context;
import org.nutz.mvc.ActionContext;
import org.nutz.mvc.Loading;
import org.nutz.mvc.Mvcs;
import org.nutz.mvc.View;
import org.nutz.mvc.config.AtMap;
import org.nutz.mvc.impl.processor.ViewProcessor;

/**
 * @author mawm(ming300@gmail.com)
 * @author wendal(wendal1985@gmail.com)
 */
public abstract class AbstractPathView implements View {

    private Segment dest;

    private Map<String, El> exps;

    public AbstractPathView(String dest) {
        if (null != dest) {
            this.dest = new CharSegment(Strings.trim(dest));
            this.exps = new HashMap<String, El>();
            // 预先将每个占位符解析成表达式
            for (String key : this.dest.keys()) {
                this.exps.put(key, new El(key));
            }
        }
    }

    protected String evalPath(HttpServletRequest req, Object obj) {
        if (null == dest)
            return null;

        Context context = Lang.context();

        // 解析每个表达式
        if (exps.size() != 0) {
        	Context expContext = createContext(req, obj);
        	for (Entry<String, El> en : exps.entrySet())
        		context.set(en.getKey(), en.getValue().eval(expContext));
        }
        // 生成解析后的路径
        return Strings.trim(this.dest.render(context).toString());
    }

    /**
     * 为一次 HTTP 请求，创建一个可以被表达式引擎接受的上下文对象
     *
     * @param req
     *            HTTP 请求对象
     * @param obj
     *            入口函数的返回值
     * @return 上下文对象
     */
    public static Context createContext(HttpServletRequest req, Object obj) {
        Context context = Lang.context();
        // 复制全局的上下文对象
        Object globalContext = Mvcs.getServletContext()
                                   .getAttribute(Loading.CONTEXT_NAME);
        if (globalContext != null) {
            context.putAll((Context) globalContext);
        }

        // 请求对象的属性列表
        Map<String, Object> req_attr = new HashMap<String, Object>();
        for (Enumeration<String> en = req.getAttributeNames(); en.hasMoreElements();) {
            String tem = en.nextElement();
            if (!tem.startsWith("$"))
                req_attr.put(tem, req.getAttribute(tem));
        }
        context.set("a", req_attr);// 兼容最初的写法
        context.set("req_attr", req_attr);

        ActionContext ac = Mvcs.getActionContext();
        if (ac != null)
            context.set("pathargs", Mvcs.getActionContext().getPathArgs());

        try {
            HttpSession session = Mvcs.getHttpSession(false);
            if (session != null) {
                Map<String, Object> session_attr = new HashMap<String, Object>();
                for (Enumeration<String> en = session.getAttributeNames(); en.hasMoreElements();) {
                    String tem = en.nextElement();
                    session_attr.put(tem, session.getAttribute(tem));
                }
                context.set("session_attr", session_attr);
            }
        }
        catch (Throwable e) {
            // noop
        }
        // 请求的参数表,需要兼容之前的p.参数, Fix issue 418
        Map<String, String> p = new HashMap<String, String>();
        for (Object o : Lang.enum2collection(req.getParameterNames(), new ArrayList<String>())) {
            String key = (String) o;
            String value = req.getParameter(key);
            p.put(key, value);
            context.set(key, value);// 以支持直接获取请求参数
        }
        context.set("p", p);

        Map<String, String> u = new HashMap<String, String>();
        AtMap at = Mvcs.getAtMap();
        if (at != null) {
            for (Object o : at.keys()) {
                String key = (String) o;
                u.put(key, at.get(key));
            }
            context.set("u", u);
        }

        // 加入返回对象
        if (null != obj)
            context.set(ViewProcessor.DEFAULT_ATTRIBUTE, obj);
        return context;
    }
}


package org.nutz.mvc;

import org.nutz.Nutz;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.IocContext;
import org.nutz.json.Json;
import org.nutz.json.JsonFormat;
import org.nutz.lang.Strings;
import org.nutz.lang.util.Context;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.config.AtMap;
import org.nutz.mvc.impl.NutMessageMap;
import org.nutz.mvc.ioc.SessionIocContext;

import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URLDecoder;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Mvc 相关帮助函数
 *
 * @author zozoh(zozohtnt@gmail.com)
 * @author wendal(wendal1985@gmail.com)
 */
public abstract class Mvcs {

    // TODO 这个变量应该在 1.b.46 之后的某一个版本删掉
    public static final String DEFAULT_MSGS = "$default";

    public static final String MSG = "msg";
    public static final String LOCALE_KEY = "nutz_mvc_localization_key";

    // PS: 如果这个修改导致异常,请报issue,并将这个变量设置为true
    public static boolean disableFastClassInvoker = false;
    // 实现显示行号, 如果禁用, 轻微加速启动
    public static boolean DISPLAY_METHOD_LINENUMBER = true;
    // 如果一个Resp已经commit过了,那么是否跳过渲染呢
    public static boolean SKIP_COMMITTED = false;

    public static boolean DISABLE_X_POWERED_BY = false;

    public static String X_POWERED_BY = "nutz/"+Nutz.version()+" <nutzam.com>";

    // ====================================================================

    public static Map<String, Object> getLocaleMessage(String key) {
        Map<String, Map<String, Object>> msgss = getMessageSet();
        if (null != msgss)
            return msgss.get(key);
        return null;
    }

    /**
     * 获取当前请求对象的字符串表
     *
     * @param req
     *            请求对象
     * @return 字符串表
     */
    @SuppressWarnings("unchecked")
    public static Map<String, String> getMessages(ServletRequest req) {
        return (Map<String, String>) req.getAttribute(MSG);
    }

    /**
     * 获取当前请求对象的字符串表（NutMessageMap 封装）
     *
     * @param req
     *            请求对象
     * @return 字符串表
     */
    public static NutMessageMap getMessageMap(ServletRequest req) {
        return (NutMessageMap) req.getAttribute(MSG);
    }

    /**
     * 获取当前请求对象的字符串表中的某一个字符串
     *
     * @param req
     *            请求对象
     * @param key
     *            字符串键值
     * @return 字符串内容
     */
    public static String getMessage(ServletRequest req, String key) {
        Map<String, String> map = getMessages(req);
        if (null != map)
            return map.get(key);
        return null;
    }

    /**
     * 获取当前会话的本地字符串集合的键值；如果当前 HTTP 会话不存在，则返回 null
     *
     * @return 当前会话的本地字符串集合的键值；如果当前 HTTP 会话不存在，则返回 null
     */
    public static String getLocalizationKey() {
        return (String) getSessionAttrSafe(LOCALE_KEY);
    }

    /**
     * 设置本地化字符串的键值
     *

     * 如果你用的是 Nutz.Mvc 默认的本地化机制，那么你的本地字符串键值，相当于一个你目录名。

     * 比如 "zh_CN" 等
     *
     * @param key
     *            键值
     * @return 是否设置成功
     */
    public static boolean setLocalizationKey(String key) {
        HttpSession sess = getHttpSession();
        if (null == sess)
            return false;
        sess.setAttribute(LOCALE_KEY, key);
        return true;
    }

    /**
     * 返回当前加载了的本地化字符串的键值
     *
     * @return 当前都加载了哪些种字符串的 KEY
     */
    public static Set<String> getLocalizationKeySet() {
        Map<String, Map<String, Object>> msgss = getMessageSet();
        if (null == msgss)
            return new HashSet<String>();
        return msgss.keySet();
    }

    /**
     * 默认的本地化字符串 KEY，当为 NULL 时，Nutz.Mvc 会随便用一个
     */
    private static String default_localization_key = null;

    /**
     * 设置默认的多国语言
     *
     * @param key
     *            默认的多国语言 KEY
     */
    public static void setDefaultLocalizationKey(String key) {
        default_localization_key = key;
    }

    /**
     * 返回默认的本地化字符串 KEY
     *
     * @return 默认的本地化字符串 KEY
     */
    public static String getDefaultLocalizationKey() {
        return default_localization_key;
    }

    /**
     * 为当前的 HTTP 请求对象设置一些必要的属性。包括：
     *

     *
本地化子字符串 => ${msg}
     *
应用的路径名 => ${base}
     *

     *
     * @param req
     *            HTTP 请求对象
     */
    public static void updateRequestAttributes(HttpServletRequest req) {
        // 初始化本次请求的多国语言字符串
        Map<String, Map<String, Object>> msgss = getMessageSet();
        if (msgss == null && !ctx().localizations.isEmpty())
            msgss = ctx().localizations.values().iterator().next();
        if (null != msgss) {
            Map<String, Object> msgs = null;

            String lKey = Strings.sBlank(Mvcs.getLocalizationKey(), getDefaultLocalizationKey());

            if (!Strings.isBlank(lKey))
                msgs = msgss.get(lKey);

            // 没有设定特殊的 Local 名字，随便取一个
            if (null == msgs) {
                if (msgss.size() > 0)
                    msgs = msgss.values().iterator().next();
            }
            // 记录到请求中
            req.setAttribute(MSG, msgs);
        }

        // 记录一些数据到请求对象中
        req.setAttribute("base", req.getContextPath());
        req.setAttribute("$request", req);
    }

    /**
     * 获取当前请求的路径，并去掉后缀
     *
     * @param req
     *            HTTP 请求对象
     */
    public static String getRequestPath(HttpServletRequest req) {
        return getRequestPathObject(req).getPath();
    }

    /**
     * 获取当前请求的路径，并去掉后缀
     *
     * @param req
     *            HTTP 请求对象
     */
    public static RequestPath getRequestPathObject(HttpServletRequest req) {
        String url = req.getPathInfo();
        if (null == url)
            url = req.getServletPath();
        return getRequestPathObject(url);
    }

    /**
     * 获取当前请求的路径，并去掉后缀
     *
     * @param url
     *            请求路径的URL
     */
    public static RequestPath getRequestPathObject(String url) {
        RequestPath rr = new RequestPath();
        rr.setUrl(url);
        if (null != url) {
            int lio = 0;
            if (!url.endsWith("/")) {
                int ll = url.lastIndexOf('/');
                lio = url.lastIndexOf('.');
                if (lio < ll)
                    lio = -1;
            }
            if (lio > 0) {
                rr.setPath(url.substring(0, lio));
                rr.setSuffix(url.substring(lio + 1));
            } else {
                rr.setPath(url);
                rr.setSuffix("");
            }
        } else {
            rr.setPath("");
            rr.setSuffix("");
        }
        return rr;
    }

    /**
     * 注销当前 HTTP 会话。所有 Ioc 容器存入的对象都会被注销
     *
     * @param session
     *            HTTP 会话对象
     */
    public static void deposeSession(HttpSession session) {
        if (session != null)
            new SessionIocContext(session).depose();
    }

    /**
     * 它将对象序列化成 JSON 字符串，并写入 HTTP 响应
     *
     * @param resp
     *            响应对象
     * @param obj
     *            数据对象
     * @param format
     *            JSON 的格式化方式
     * @throws IOException
     *             写入失败
     */
    public static void write(HttpServletResponse resp, Object obj, JsonFormat format)
            throws IOException {
        write(resp, resp.getWriter(), obj, format);
    }

    public static void write(HttpServletResponse resp, Writer writer, Object obj, JsonFormat format)
            throws IOException {
        resp.setHeader("Cache-Control", "no-cache");
        if (resp.getContentType() == null)
            resp.setContentType("text/plain");

        // by mawm 改为直接采用resp.getWriter()的方式直接输出!
        Json.toJson(writer, obj, format);

        resp.flushBuffer();
    }

    // ==================================================================
    private static final ThreadLocal<String> NAME = new ThreadLocal<String>();

    /**
     * NutMvc的上下文
     */
    @Deprecated
    public static NutMvcContext ctx;

    public static NutMvcContext ctx() {
        ServletContext sc = getServletContext();
        if (sc == null) {
            if (ctx == null)
                ctx = new NutMvcContext();
            return ctx;
        }
        NutMvcContext c = (NutMvcContext) getServletContext().getAttribute("__nutz__mvc__ctx");
        if (c == null) {
            c = new NutMvcContext();
            getServletContext().setAttribute("__nutz__mvc__ctx", c);
            ctx = c;
        }
        return c;
    }

    private static ServletContext def_servletContext;
    private static ThreadLocal<ServletContext> servletContext = new ThreadLocal<ServletContext>();

    /**
     * 获取 HTTP 请求对象
     *
     * @return HTTP 请求对象
     */
    public static final HttpServletRequest getReq() {
        return reqt().getAs(HttpServletRequest.class, "req");
    }

    /**
     * 获取 HTTP 响应对象
     *
     * @return HTTP 响应对象
     */
    public static final HttpServletResponse getResp() {
        return reqt().getAs(HttpServletResponse.class, "resp");
    }

    public static final String getName() {
        return NAME.get();
    }

    /**
     * 获取 Action 执行的上下文
     *
     * @return Action 执行的上下文
     */
    public static final ActionContext getActionContext() {
        return reqt().getAs(ActionContext.class, "ActionContext");
    }

    public static void set(String name, HttpServletRequest req, HttpServletResponse resp) {
        NAME.set(name);
        reqt().set("req", req);
        reqt().set("resp", resp);
    }

    /**
     * 设置 Servlet 执行的上下文
     *
     * @param servletContext
     *            Servlet 执行的上下文
     */
    public static void setServletContext(ServletContext servletContext) {
        if (servletContext == null) {
            Mvcs.servletContext.remove();
        }
        if (def_servletContext == null)
            def_servletContext = servletContext;
        Mvcs.servletContext.set(servletContext);
    }

    /**
     * 设置 Action 执行的上下文
     *
     * @param actionContext
     *            Action 执行的上下文
     */
    public static void setActionContext(ActionContext actionContext) {
        reqt().set("ActionContext", actionContext);
    }

    /**
     * 获取 Servlet 执行的上下文
     *
     * @return Servlet 执行的上下文
     */
    public static ServletContext getServletContext() {
        ServletContext cnt = servletContext.get();
        if (cnt != null)
            return cnt;
        return def_servletContext;
    }

    /**
     * 设置对象装配的上下文环境
     *
     * @param iocContext
     *            对象装配的上下文环境
     */
    public static void setIocContext(IocContext iocContext) {
        reqt().set("IocContext", iocContext);
    }

    /**
     * 获取对象装配的上下文环境
     *
     * @return 进行对象装配的上下文环境
     */
    public static IocContext getIocContext() {
        return reqt().getAs(IocContext.class, "IocContext");
    }

    // 新的,基于ThreadLoacl改造过的Mvc辅助方法
    // ====================================================================

    /**
     * 获取全局的Ioc对象
     *
     * @return 全局的Ioc对象
     */
    public static Ioc getIoc() {
        return ctx().iocs.get(getName());
    }

    public static void setIoc(Ioc ioc) {
        ctx().iocs.put(getName(), ioc);
    }

    public static AtMap getAtMap() {
        return ctx().atMaps.get(getName());
    }

    public static void setAtMap(AtMap atmap) {
        ctx().atMaps.put(getName(), atmap);
    }

    public static Map<String, Map<String, Object>> getMessageSet() {
        return ctx().localizations.get(getName());
    }

    public static void setMessageSet(Map<String, Map<String, Object>> messageSet) {
        ctx().localizations.put(getName(), messageSet);
    }

    public static void setNutConfig(NutConfig config) {
        ctx().nutConfigs.put(getName(), config);
    }

    public static NutConfig getNutConfig() {
        return ctx().nutConfigs.get(getName());
    }

    // ==================================================================

    /**
     * 重置当前线程所持有的对象
     */
    public static Context resetALL() {
        Context context = reqt();
        NAME.set(null);
        ctx().removeReqCtx();
        return context;
    }

    public static HttpSession getHttpSession() {
        return getHttpSession(true);
    }

    public static HttpSession getHttpSession(boolean createNew) {
        HttpServletRequest req = getReq();
        if (null == req)
            return null;
        return req.getSession(createNew);
    }

    public static void close() {
        ctx().clear();
        ctx().close();
        ctx = new NutMvcContext();
    }

    public static Context reqt() {
        return ctx().reqCtx();
    }

    public static Object getSessionAttrSafe(String key) {
        try {
            HttpSession session = getHttpSession(false);
            return session != null ? session.getAttribute(key) : null;
        }
        catch (Exception e) {
            return false;
        }
    }

    public static void setSessionAttrSafe(String key, Object val, boolean sessionCreate) {
        try {
            HttpSession session = getHttpSession(sessionCreate);
            if (session != null)
                session.setAttribute(key, val);
        }
        catch (Exception e) {
        }
    }

    public static NutMap toParamMap(Reader r, String enc) throws IOException {
        try {
            NutMap map = new NutMap();
            char[] buf = new char[1];
            StringBuilder sb = new StringBuilder();
            while (true) {
                int len = r.read(buf);
                if (len == 0)
                    continue;
                if (buf[0] == '&' || len < 0) {
                    String[] tmp = sb.toString().split("=");
                    if (tmp != null && tmp.length == 2) {
                        map.put(URLDecoder.decode(tmp[0], enc), URLDecoder.decode(tmp[1], enc));
                    }
                    if (len < 0)
                        break;
                    sb.setLength(0);
                } else {
                    sb.append(buf[0]);
                }
            }
            return map;
        }
        catch (UnsupportedEncodingException e) {
            throw new IOException(e);
        }
    }

}


package org.nutz.json.entity;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;

import org.nutz.json.JsonField;
import org.nutz.json.JsonIgnore;
import org.nutz.lang.Lang;
import org.nutz.lang.Mirror;
import org.nutz.lang.Strings;
import org.nutz.lang.eject.EjectByGetter;
import org.nutz.lang.eject.Ejecting;
import org.nutz.lang.inject.InjectBySetter;
import org.nutz.lang.inject.Injecting;
import org.nutz.lang.reflect.ReflectTool;

public class JsonEntityField {

    private String name;

    private boolean ignore;

    private Type genericType;

    private Injecting injecting;

    private Ejecting ejecting;

    private boolean forceString;

    private double ignoreNullDouble = -0.94518;

    private int ignoreNullInt = -94518;

    private boolean isInt;

    private boolean isDouble;

    private boolean hasJsonIgnore;

    private Format dataFormat;

    private Mirror<?> mirror;

    private Class<?> declaringClass;

    public boolean isForceString() {
        return forceString;
    }

    public void setForceString(boolean forceString) {
        this.forceString = forceString;
    }

    public boolean isIgnore() {
        return ignore;
    }

    public void setIgnore(boolean ignore) {
        this.ignore = ignore;
    }

    /**
     * 根据名称获取字段实体, 默认以set优先
     */
    public static JsonEntityField eval(Mirror<?> mirror, String name, Method getter, Method setter) {
        JsonEntityField jef = new JsonEntityField();
        jef.declaringClass = mirror.getType();
        jef.setGenericType(getter.getGenericReturnType());
        jef.name = name;
        jef.ejecting = new EjectByGetter(getter);
        jef.injecting = new InjectBySetter(setter);
        jef.mirror = Mirror.me(getter.getReturnType());
        return jef;
    }

    public static JsonEntityField eval(Mirror<?> mirror, String name, Type type, Ejecting ejecting, Injecting injecting) {
        JsonEntityField jef = new JsonEntityField();
        jef.genericType = mirror.getType();
        jef.setGenericType(type);
        jef.name = name;
        jef.ejecting = ejecting;
        jef.injecting = injecting;
        jef.mirror = Mirror.me(type);
        return jef;
    }

    @SuppressWarnings({"deprecation", "rawtypes"})
    public static JsonEntityField eval(Mirror<?> mirror, Field fld) {
        if (fld == null) {
            return null;
        }

        // 以特殊字符开头的字段，看起来是隐藏字段
        // XXX 有用户就是_开头的字段也要啊! by wendal
        // if (fld.getName().startsWith("_") || fld.getName().startsWith("$"))
        if (fld.getName().startsWith("$")
            && fld.getAnnotation(JsonField.class) == null)
            return null;

        JsonField jf = fld.getAnnotation(JsonField.class);

        JsonEntityField jef = new JsonEntityField();
        jef.declaringClass = mirror.getType();
        jef.setGenericType(Lang.getFieldType(mirror, fld));
        jef.name = Strings.sBlank(null == jf ? null : jf.value(), fld.getName());
        jef.ejecting = mirror.getEjecting(fld.getName());
        jef.injecting = mirror.getInjecting(fld.getName());
        jef.mirror = Mirror.me(fld.getType());

        // 瞬时变量和明确声明忽略的，变 ignore
        if (Modifier.isTransient(fld.getModifiers())
            || (null != jf && jf.ignore())) {
            jef.setIgnore(true);
        }

        // 判断字段是否被强制输出为字符串
        if (null != jf) {
            jef.setForceString(jf.forceString());
            String dataFormat = jf.dataFormat();
            if(Strings.isBlank(dataFormat)){
                dataFormat = jf.dateFormat();
            }
            if(!Strings.isBlank(dataFormat)){
                Mirror jfmirror = Mirror.me(jef.genericType);
                if(jfmirror.isNumber()){
                    jef.dataFormat = new DecimalFormat(dataFormat);
                }else if(jfmirror.isDateTimeLike()){
                    DateFormat df = null;
                    if (Strings.isBlank(jf.locale())) {
                        df = new SimpleDateFormat(dataFormat);
                    }
                    else {
                        df = new SimpleDateFormat(dataFormat, Locale.forLanguageTag(jf.locale()));
                    }
                    if (!Strings.isBlank(jf.timeZone())) {
                        df.setTimeZone(TimeZone.getTimeZone(jf.timeZone()));
                    }
                    jef.dataFormat = df;
                }
            }
        }

        JsonIgnore jsonIgnore = fld.getAnnotation(JsonIgnore.class);
        if (jsonIgnore != null) {
            Mirror<?> fldMirror = Mirror.me(fld.getType());
            jef.isInt = fldMirror.isInt();
            jef.isDouble = fldMirror.isDouble() || fldMirror.isFloat();
        	jef.hasJsonIgnore = true;
            if (jef.isDouble)
            	jef.ignoreNullDouble = jsonIgnore.null_double();
            if (jef.isInt)
            	jef.ignoreNullInt = jsonIgnore.null_int();
        }

        return jef;
    }

    private JsonEntityField() {}

    public String getName() {
        return name;
    }

    public Type getGenericType() {
        return genericType;
    }

    public void setValue(Object obj, Object value) {
        if (injecting != null)
            injecting.inject(obj, value);
    }

    public Object getValue(Object obj) {
        if (ejecting == null)
            return null;
        Object val = ejecting.eject(obj);
        if (val == null)
        	return null;
        if (hasJsonIgnore) {
            if (isInt && ((Number)val).intValue() == ignoreNullInt)
            	return null;
            if (isDouble && ((Number)val).doubleValue() == ignoreNullDouble)
            	return null;
        }
        return val;
    }

    public Format getDataFormat() {
        return dataFormat == null ? null : (Format)dataFormat.clone();
    }

    public boolean hasDataFormat() {
        return dataFormat != null;
    }

    public Mirror<?> getMirror() {
        return mirror;
    }

    public void setGenericType(Type genericType) {
        this.genericType = ReflectTool.getInheritGenericType(declaringClass, genericType);;
    }

    public void setInjecting(Injecting injecting) {
        this.injecting = injecting;
    }

    public void setEjecting(Ejecting ejecting) {
        this.ejecting = ejecting;
    }
}


package org.nutz.dao.impl.sql;

import org.nutz.lang.util.LinkedArray;
import org.nutz.lang.util.LinkedCharArray;

/**
 * 通过 add 函数，可以增加需要逃逸的字符，以及如何逃逸
 * <p>
 * 然后调用 escape 函数，执行逃逸
 *
 * @author zozoh(zozohtnt@gmail.com)
 *
 */
public class ValueEscaper {

    public ValueEscaper() {
        this.charStack = new LinkedCharArray(20);
        this.escapeStack = new LinkedArray<String>(20);
    }

    private LinkedCharArray charStack;
    private LinkedArray<String> escapeStack;
    private char[] chars;
    private String[] escapes;

    /**
     * 设定逃逸方式
     *
     * @param c
     *            要逃逸的字符
     * @param s
     *            如何逃逸
     * @return 自身
     */
    public ValueEscaper add(char c, String s) {
        charStack.push(c);
        escapeStack.push(s);
        return this;
    }

    /**
     * 在执行 escape 前，这个函数一定要调用，它会把你增加的逃逸设置，初始化一下
     *
     * @return 自身
     */
    public ValueEscaper ready() {
        chars = charStack.toArray();
        escapes = escapeStack.toArray();
        return this;
    }

    /**
     * 根据逃逸的设置，对传入的字符串进行逃逸
     *
     * @param cs
     *            字符序列
     * @return 逃逸后的字符序列
     */
    public CharSequence escape(CharSequence cs) {
        StringBuilder sb = new StringBuilder();
        boolean find;
        for (int i = 0; i < cs.length(); i++) {
            char c = cs.charAt(i);
            find = false;
            for (int x = 0; x < chars.length; x++) {
                if (c == chars[x]) {
                    sb.append(escapes[x]);
                    find = true;
                    break;
                }
            }
            if (!find)
                sb.append(c);
        }
        return sb;
    }

}


package org.nutz.lang.reflect;

import org.nutz.lang.Lang;

import java.lang.reflect.Field;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;

@SuppressWarnings({"unchecked", "rawtypes"})
public class ReflectTool {

    private static Method DEFINE_CLASS;
    private static final ProtectionDomain PROTECTION_DOMAIN;

    static {
        PROTECTION_DOMAIN = getProtectionDomain(ReflectTool.class);

        AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                try {
                    Class loader = Class.forName("java.lang.ClassLoader"); // JVM
                                                                           // crash
                                                                           // w/o
                                                                           // this
                    DEFINE_CLASS = loader.getDeclaredMethod("defineClass",
                                                            new Class[]{String.class,
                                                                        byte[].class,
                                                                        Integer.TYPE,
                                                                        Integer.TYPE,
                                                                        ProtectionDomain.class});
                    DEFINE_CLASS.setAccessible(true);
                }
                catch (ClassNotFoundException e) {
                    // Lang.impossible();
                }
                catch (NoSuchMethodException e) {
                    // Lang.impossible();
                }
                return null;
            }
        });
    }

    public static ProtectionDomain getProtectionDomain(final Class source) {
        if (source == null) {
            return null;
        }
        return (ProtectionDomain) AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                return source.getProtectionDomain();
            }
        });
    }

    public static Class defineClass(String className, byte[] b, ClassLoader loader)
            throws Exception {
        return defineClass(className, b, loader, PROTECTION_DOMAIN);
    }

    public static Class defineClass(String className,
                                    byte[] b,
                                    ClassLoader loader,
                                    ProtectionDomain protectionDomain) throws Exception {
        Object[] args = new Object[]{className,
                                     b,
                                     new Integer(0),
                                     new Integer(b.length),
                                     protectionDomain};
        if (loader == null)
            loader = ReflectTool.class.getClassLoader();
        Class c = (Class) DEFINE_CLASS.invoke(loader, args);
        // Force static initializers to run.
        Class.forName(className, true, loader);
        return c;
    }

    /**
     * 泛型类clazz,field字段的真实class对象.
     * @param clazz 泛型class
     * @param field 字段
     * @return
     */
    public static Class<?> getGenericFieldType(Class<?> clazz, Field field) {
        Type fieldType = field.getGenericType();
        return getRealGenericClass(clazz, fieldType);
    }

    /**
     * 获取泛型类参数的实际类型.例如 Map<String, E>，获取E实际的类型.
     * @param clazz 泛型基类.
     * @param type 泛型基类中的某个type
     * @return
     */
    public static Class<?> getParameterRealGenericClass(Class<?> clazz, Type type, int index) {
        if (type instanceof ParameterizedType) {
            Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
            return getRealGenericClass(clazz, actualTypeArguments[index]);
        }
        return Object.class;
    }

    /**
     * 获取泛型类中type变量对应的真实class
     * @param clazz 泛型基类.
     * @param type 泛型基类中的某个type
     * @return
     */
    public static Class<?> getRealGenericClass(Class<?> clazz, Type type) {
        if(type instanceof TypeVariable) {
            TypeVariable<?> tv = (TypeVariable<?>) type;
            Type genericFieldType = getInheritGenericType(clazz, tv);
            if (genericFieldType != null) {
                return Lang.getTypeClass(genericFieldType);
            }
        }
        return Lang.getTypeClass(type);
    }

    /**
     * 获取泛型类中type对应的真实Type
     * @param clazz
     * @param type
     * @return
     */
    public static Type getInheritGenericType(Class<?> clazz, Type type) {
        if(type instanceof TypeVariable) {
            TypeVariable<?> tv = (TypeVariable<?>) type;
            return getInheritGenericType(clazz, tv);
        }else {
            return type;
        }
    }

    /**
     * 获取泛型类clazz中某个TypeVariable对应的真实Type.
     * @param clazz
     * @param tv
     * @return
     */
    public static Type getInheritGenericType(Class<?> clazz, TypeVariable<?> tv) {
        Type type = null;
        GenericDeclaration gd = tv.getGenericDeclaration();

        do {
            type = clazz.getGenericSuperclass();
            if (type == null) {
                return null;
            }
            if (type instanceof ParameterizedType) {
                ParameterizedType ptype = (ParameterizedType) type;

                Type rawType = ptype.getRawType();
                boolean eq = gd.equals(rawType) || (gd instanceof Class && rawType instanceof Class && ((Class) gd).isAssignableFrom((Class) rawType));
                if (eq) {
                    TypeVariable<?>[] tvs = gd.getTypeParameters();
                    Type[] types = ptype.getActualTypeArguments();
                    for (int i = 0; i < tvs.length; i++) {
                        if (tv.equals(tvs[i])) {
                            return types[i];
                        }
                    }
                    return null;
                }
            }
            clazz = Lang.getTypeClass(type);
        } while (type != null);
        return null;
    }
}


package org.nutz.http;

import org.nutz.lang.Encoding;
import org.nutz.lang.Lang;
import org.nutz.lang.Streams;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;

import java.io.*;
import java.net.HttpURLConnection;
import java.nio.charset.Charset;
import java.util.Map;

public class Response {
    private static final String DEF_PROTOCAL_VERSION = "HTTP/1.1";

    public Response() {
    }

    public Response(HttpURLConnection conn, Map<String, String> reHeader) throws IOException {
        status = conn.getResponseCode();
        detail = conn.getResponseMessage();
        this.header = Header.create(reHeader);
        String s = header.get("Set-Cookie");
        if (null != s) {
            this.cookie = new Cookie();
            this.cookie.afterResponse(null, conn, null); // 解决多个Set-Cookie丢失的问题
        }
        encode = getEncodeType();
    }

    public Response(HttpURLConnection conn, NutMap reHeader) throws IOException {
        status = conn.getResponseCode();
        detail = conn.getResponseMessage();
        this.header = Header.create(reHeader);
        String s = header.get("Set-Cookie");
        if (null != s) {
            this.cookie = new Cookie();
            this.cookie.afterResponse(null, conn, null); // 解决多个Set-Cookie丢失的问题
        }
        encode = getEncodeType();
    }

    private Header header;
    private InputStream stream;
    private Cookie cookie;
    private String protocol = DEF_PROTOCAL_VERSION;
    private int status;
    private String detail;
    private String content;
    private String encode;

    public String getProtocol() {
        return protocol;
    }

    @Deprecated
    public String getProtocal() {
        return protocol;
    }

    public int getStatus() {
        return status;
    }

    public String getDetail() {
        return detail;
    }

    public boolean isOK() {
        return status == 200;
    }

    public boolean isServerError() {
        return status >= 500 && status < 600;
    }

    public boolean isClientError() {
        return status >= 400 && status < 500;
    }

    void setStream(InputStream stream) {
        this.stream = stream;
    }

    public Header getHeader() {
        return header;
    }

    /**
     * 根据Http头的Content-Type获取网页的编码类型，如果没有设的话则返回null
     */
    public String getEncodeType() {
        String contentType = header.get("Content-Type");
        if (null != contentType) {
            for (String tmp : contentType.split(";")) {
                if (tmp == null)
                    continue;
                tmp = tmp.trim();
                if (tmp.startsWith("charset=")) {
                    tmp = Strings.trim(tmp.substring(8)).trim();
                    if (tmp.contains(","))
                        tmp = tmp.substring(0, tmp.indexOf(',')).trim();
                    return tmp;
                }
            }
        }
        return Encoding.UTF8;
    }

    public void setEncode(String encode) {
        this.encode = encode;
    }

    public String getEncode() {
        return encode;
    }

    public InputStream getStream() {
        return new BufferedInputStream(stream);
    }

    public Reader getReader() {
        String encoding = this.getEncodeType();
        if (null == encoding)
            return getReader(Encoding.defaultEncoding());
        else
            return getReader(encoding);
    }

    public Reader getReader(String charsetName) {
        if (content != null)
            return new StringReader(charsetName);
        return new InputStreamReader(getStream(), Charset.forName(charsetName));
    }

	public Reader getReader(Charset charset) {

        if (charset == null) {
            throw new IllegalArgumentException("charset can not be null");
        }

        return getReader(charset.name());
    }
    public Cookie getCookie() {
        return cookie;
    }

    public void printHeader(Writer writer) {
        try {
            writer.write(header.toString());
        }
        catch (IOException e) {
            throw Lang.wrapThrow(e);
        }
    }

    public void print(Writer writer) {
        print(writer, null);
    }

    public void print(Writer writer, String charsetName) {
        Reader reader = null;
        try {
            if (null == charsetName)
                reader = getReader();
            else
                reader = this.getReader(charsetName);
            int c;
            char[] buf = new char[8192];
            while (-1 != (c = reader.read(buf))) {
                writer.write(buf, 0, c);
            }
            writer.flush();
        }
        catch (IOException e) {
            throw Lang.wrapThrow(e);
        }
    }

    public String getContent() {
        return getContent(encode);
    }

    public String getContent(String charsetName) {
        if (content == null) {
            if (charsetName == null)
                content = Streams.readAndClose(getReader(encode));
            else
                content = Streams.readAndClose(getReader(charsetName));
        }
        return content;
    }
}


package org.nutz.lang.segment;

import java.io.File;
import java.util.Map;

import org.nutz.lang.Files;
import org.nutz.lang.Lang;
import org.nutz.lang.util.Context;
import org.nutz.lang.util.NutMap;

/**
 * 代码片段的帮助函数
 *
 * @author zozoh(zozohtnt@gmail.com)
 */
public class Segments {

    /**
     * 根据一个对象填充所有片段的占位符
     *
     * @param seg
     *            片段
     * @param obj
     *            对象
     * @return 填充后的片段对象
     */
    public static Segment fill(Segment seg, Object obj) {
        if (null == obj || null == seg)
            return seg;
        return seg.setBy(obj);
    }

    /**
     * 根据一个文件生成一个代码片段
     *
     * @param f
     *            文件
     * @return 片段对象
     */
    public static Segment read(File f) {
        String txt = Files.read(f);
        return new CharSegment(txt);
    }

    /**
     * 根据字符串片段，将上下文对象替换对应占位符。未赋值的占位符维持原样
     * <p>
     * 比如：
     *
     * @param seg
     *            片段对象
     * @param context
     *            上下文对象
     * @return 替换后的字符串
     */
    public static String replace(Segment seg, Context context) {
        if (null == seg)
            return null;

        // 增加缺失的占位符号
        for (String key : seg.keys())
            if (!context.has(key))
                context.set(key, "${" + key + "}");

        return seg.render(context).toString();
    }

    /**
     * 根据字符串片段，将上下文对象替换对应占位符。未赋值的占位符维持原样
     *
     * @param pattern
     *            字符串片段
     * @param context
     *            上下文对象
     * @return 替换后的字符串
     */
    public static String replace(String pattern, Context context) {
        if (null == pattern)
            return null;
        if (null == context)
            return pattern;
        return replace(new CharSegment(pattern), context);
    }

    /**
     * @see #replace(Segment, Context)
     */
    public static String replace(String pattern, Map<String, Object> context) {
        return replace(pattern, Lang.context(new NutMap(context)));
    }

    /**
     * 根据一段字符串生成一个代码片段
     *
     * @param str
     *            字符串
     * @return 片段对象
     */
    public static Segment create(String str) {
        return new CharSegment(str);
    }
}


package org.nutz.dao.impl.entity.info;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.nutz.dao.DaoException;
import org.nutz.dao.entity.annotation.ColDefine;
import org.nutz.dao.entity.annotation.Column;
import org.nutz.dao.entity.annotation.Comment;
import org.nutz.dao.entity.annotation.Default;
import org.nutz.dao.entity.annotation.Id;
import org.nutz.dao.entity.annotation.Many;
import org.nutz.dao.entity.annotation.ManyMany;
import org.nutz.dao.entity.annotation.Name;
import org.nutz.dao.entity.annotation.Next;
import org.nutz.dao.entity.annotation.One;
import org.nutz.dao.entity.annotation.PK;
import org.nutz.dao.entity.annotation.Prev;
import org.nutz.dao.entity.annotation.Readonly;
import org.nutz.lang.Lang;
import org.nutz.lang.Mirror;
import org.nutz.lang.eject.EjectByGetter;
import org.nutz.lang.inject.InjectBySetter;
import org.nutz.lang.util.Callback3;

public class _Infos {

    private final static String ERR_MSG = "Method '%s'(%s) can not add '@Column', it MUST be a setter or getter!";

    @SuppressWarnings("rawtypes")
    private static <T extends FieldInfo> T create(Class<T> classOfT, Field field) {
        T info = Mirror.me(classOfT).born();
        info.name = field.getName();
        // XXX 兼容性改变 从1.b.51开始, 优先走getter/setter
        // 老版本是只从属性取值/设置值,不走getter/setter
        info.fieldType = field.getGenericType();
        Mirror me = Mirror.me(field.getDeclaringClass());
        info.injecting = me.getInjecting(field.getName());
        info.ejecting = me.getEjecting(field.getName());
        return info;
    }

    private static <T extends FieldInfo> T create(Class<T> classOfT, final Method method) {
        final T info = Mirror.me(classOfT).born();
        Mirror.evalGetterSetter(method, ERR_MSG, new Callback3<String, Method, Method>() {
            public void invoke(String name, Method getter, Method setter) {
                // 木有 getter
                if (null == getter) {
                    throw Lang.makeThrow(    "Method '%s'(%s) has '@Column', but NO setter!",
                                            method.getName(),
                                            method.getDeclaringClass().getName());
                }
                // 木有 setter
                if (null == setter) {
                    throw Lang.makeThrow(    "Method '%s'(%s) has '@Column', but NO setter!",
                                            method.getName(),
                                            method.getDeclaringClass().getName());
                }
                // 正常，开始设值
                info.name = name;
                info.fieldType = getter.getGenericReturnType();
                info.ejecting = new EjectByGetter(getter);
                info.injecting = new InjectBySetter(setter);
            }
        });
        return info;
    }

    public static LinkInfo createLinkInfo(Method method) {
        LinkInfo info = create(LinkInfo.class, method);
        info.one = method.getAnnotation(One.class);
        info.many = method.getAnnotation(Many.class);
        info.manymany = method.getAnnotation(ManyMany.class);
        return info;
    }

    public static LinkInfo createLinkInfo(Field field) {
        LinkInfo info = create(LinkInfo.class, field);
        info.one = field.getAnnotation(One.class);
        info.many = field.getAnnotation(Many.class);
        info.manymany = field.getAnnotation(ManyMany.class);
        info.comment = field.getAnnotation(Comment.class);
        return info;
    }

    /**
     * 根据 getter/setter 函数获取一个实体字段信息对象
     *
     * @param pk
     *            复合主键
     * @param method
     *            方法：可能是 getter 或者是 setter
     * @return 字段信息对象
     */
    public static MappingInfo createMapingInfo(PK pk, Method method) {
        MappingInfo info = create(MappingInfo.class, method);
        info.annPK = pk;
        info.annColumn = method.getAnnotation(Column.class);
        info.annDefine = method.getAnnotation(ColDefine.class);
        info.annDefault = method.getAnnotation(Default.class);
        info.annId = method.getAnnotation(Id.class);
        info.annName = method.getAnnotation(Name.class);
        info.annNext = method.getAnnotation(Next.class);
        info.annPrev = method.getAnnotation(Prev.class);
        info.annReadonly = method.getAnnotation(Readonly.class);
        return info;
    }

    /**
     * 根据 Java 字段创建一个实体字段信息对象
     *
     * @param pk
     *            复合主键
     * @param field
     *            Java 字段
     * @return 字段信息对象
     */
    public static MappingInfo createMappingInfo(PK pk, Field field) {
        MappingInfo info = create(MappingInfo.class, field);
        info.annPK = pk;
        info.annColumn = field.getAnnotation(Column.class);
        info.annDefine = field.getAnnotation(ColDefine.class);
        info.annDefault = field.getAnnotation(Default.class);
        info.annId = field.getAnnotation(Id.class);
        info.annName = field.getAnnotation(Name.class);
        info.annNext = field.getAnnotation(Next.class);
        info.annPrev = field.getAnnotation(Prev.class);
        info.annReadonly = field.getAnnotation(Readonly.class);
        info.columnComment = field.getAnnotation(Comment.class);

        //检查@Id和@Name的属性类型
        if (info.annId != null) {
            if (!Mirror.me(field.getType()).isIntLike())
                throw Lang.makeThrow(DaoException.class, "Field(%s) annotation @Id , but not Number type!!", field);
        }

        if (info.annName != null)
            if (!Mirror.me(field.getType()).isStringLike())
                throw Lang.makeThrow(DaoException.class, "Field(%s) annotation @Name , but not String type!!", field);
        //检查@Version属性类型，必须是int、long、short
        if (info.annColumn != null && info.annColumn.version()){
        	Mirror<?> mirror =Mirror.me(field.getType());
        	if (!mirror.isInt() && !mirror.isShort() && !mirror.isLong())
        		throw Lang.makeThrow(DaoException.class, "Field(%s) define version=true , but not  int\\long\\short type!", field);
        }

        return info;
    }

}


package org.nutz.castor;

import java.lang.reflect.Array;
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 java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import org.nutz.castor.castor.Object2Object;
import org.nutz.conf.NutConf;
import org.nutz.lang.Lang;
import org.nutz.lang.Mirror;
import org.nutz.lang.TypeExtractor;
import org.nutz.log.Log;
import org.nutz.log.Logs;

/**
 * 一个创建 Castor 的工厂类。它的使用方式是：
 *
 *

 * Castors.me().cast(obj, fromType, toType);
 *

 *
 *
 * @author zozoh(zozohtnt@gmail.com)
 * @author Wendal(wendal1985@gmail.com)
 */
public class Castors {

    private static final Log log = Logs.get();

    /**
     * @return 单例
     */
    public static Castors me() {
        return one;
    }

    /**
     * @return 一个新的 Castors 实例
     */
    public static Castors create() {
        return new Castors();
    }

    /**
     * 如何抽取对象的类型级别
     */
    private TypeExtractor extractor;

    /**
     * Castor 的配置
     */
    private Object setting;
    private HashMap<Class<?>, Method> settingMap;

    /**
     * 设置转换的配置
     *

     * 配置对象所有的共有方法都会被遍历。只要这个方法有一个且只有一个参数，并且该参数 是一个 org.nutz.castor.Castor
     * 接口的实现类。那么就会被认为是对该种 Castor 的一个 配置。
     *

     * 当初始化这个 Castor 之前，会用这个方法来设置一下你的 Castor （如果你的 Castor 需要配置的话）
     *
     * @param obj
     *            配置对象。可以是任意的 Java 对象。
     */
    public synchronized Castors setSetting(Object obj) {
        if (obj != null) {
            setting = obj;
            this.reload();
        }
        return this;
    }

    /**
     * 设置自定义的对象类型提取器逻辑
     *
     * @param te
     *            类型提取器
     */
    public synchronized Castors setTypeExtractor(TypeExtractor te) {
        extractor = te;
        return this;
    }

    private Castors() {
        setting = new DefaultCastorSetting();
        reload();
    }

    private void reload() {
        buildSettingMap();
        // this.map =
        ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
        classes.addAll(defaultCastorList);
        for (Class<?> klass : classes) {
            try {
                if (Modifier.isAbstract(klass.getModifiers()))
                    continue;
                if (!Castor.class.isAssignableFrom(klass))
                    continue;
                fillMap(klass, settingMap, false);
            }
            catch (Throwable e) {
                if (log.isWarnEnabled())
                    log.warnf("Fail to create castor [%s] because: %s", klass, e.getMessage());
            }
        }
        if (log.isDebugEnabled())
            log.debugf("Using %s castor for Castors", map.size());
    }

    private void buildSettingMap() throws SecurityException {
        settingMap = new HashMap<Class<?>, Method>();
        for (Method m1 : setting.getClass().getMethods()) {
            Class<?>[] pts = m1.getParameterTypes();
            if (pts.length == 1 && Castor.class.isAssignableFrom(pts[0])) {
                settingMap.put(pts[0], m1);
            }
        }
    }

    public void addCastor(Class<?> klass) {
        try {
            fillMap(klass, settingMap, true);
        }
        catch (Throwable e) {
            throw Lang.wrapThrow(Lang.unwrapThrow(e));
        }
    }

    /**
     * 填充 map .

     * 在map中使用hash值来做为key来进行存储
     *
     * @param klass
     * @param settingMap
     * @param replace
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     * @throws InvocationTargetException
     */
    private void fillMap(Class<?> klass, HashMap<Class<?>, Method> settingMap, boolean replace)
            throws InstantiationException, IllegalAccessException, IllegalArgumentException,
            InvocationTargetException {
        Castor<?, ?> castor = (Castor<?, ?>) klass.newInstance();
        String key = castor.toString();
        if (!map.containsKey(key) || replace) {
            map.put(key, castor);
        } else {
            castor = map.get(key);
        }
        Method m = settingMap.get(castor.getClass());
        if (null == m) {
            for (Entry<Class<?>, Method> entry : settingMap.entrySet()) {
                Class<?> cc = entry.getKey();
                if (cc.isAssignableFrom(klass)) {
                    m = settingMap.get(cc);
                    break;
                }
            }
        }
        if (null != m)
            m.invoke(setting, castor);
    }

    /**
     * First index is "from" (source) The second index is "to" (target)
     */
    // private Map<String, Map<String, Castor<?, ?>>> map;
    // private Map<Integer, Castor<?,?>> map;
    private Map<String, Castor<?, ?>> map = new ConcurrentHashMap<String, Castor<?, ?>>();

    /**
     * 转换一个 POJO 从一个指定的类型到另外的类型
     *
     * @param src
     *            源对象
     * @param fromType
     *            源对象类型
     * @param toType
     *            目标类型
     * @param args
     *            转换时参数。有些 Castor 可能需要这个参数，比如 Array2Map
     * @return 目标对象
     * @throws FailToCastObjectException
     *             如果没有找到转换器，或者转换失败
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public <F, T> T cast(Object src, Class<F> fromType, Class<T> toType, String... args)
            throws FailToCastObjectException {
        if (null == src) {
            // 原生数据的默认值
            if (toType.isPrimitive()) {
                if (toType == int.class)
                    return (T) Integer.valueOf(0);
                else if (toType == long.class)
                    return (T) Long.valueOf(0L);
                else if (toType == byte.class)
                    return (T) Byte.valueOf((byte) 0);
                else if (toType == short.class)
                    return (T) Short.valueOf((short) 0);
                else if (toType == float.class)
                    return (T) Float.valueOf(.0f);
                else if (toType == double.class)
                    return (T) Double.valueOf(.0);
                else if (toType == boolean.class)
                    return (T) Boolean.FALSE;
                else if (toType == char.class)
                    return (T) Character.valueOf(' ');
                throw Lang.impossible();
            }
            // 是对象，直接返回 null
            return null;
        }

        if (fromType == toType || toType == null || fromType == null)
            return (T) src;

        Class<?> componentType = toType.getComponentType();
        if (null != componentType
            && fromType != String.class
            && componentType.isAssignableFrom(fromType)) {
            Object array = Array.newInstance(componentType, 1);
            Array.set(array, 0, src);
            return (T) array;
        }

        if (fromType.getName().equals(toType.getName()))
            return (T) src;
        if (toType.isAssignableFrom(fromType))
            return (T) src;
        Mirror<?> from = Mirror.me(fromType, extractor);
        Castor c = find(from, toType);
        if (null == c)
            throw new FailToCastObjectException(String.format("Can not find castor for '%s'=>'%s' in (%d) because:\n%s",
                                                              fromType.getName(),
                                                              toType.getName(),
                                                              map.size(),
                                                              "Fail to find matched castor"));
        if (Object2Object.class.getName().equals(c.getClass().getName())
            && from.canCastToDirectly(toType)) { // Use language built-in cases
            return (T) src;
        }
        try {
            return (T) c.cast(src, toType, args);
        }
        catch (FailToCastObjectException e) {
            throw e;
        }
        catch (Exception e) {
            throw new FailToCastObjectException(String.format("Fail to cast from <%s> to <%s> for {%s}",
                                                              fromType.getName(),
                                                              toType.getName(),
                                                              src),
                                                Lang.unwrapThrow(e));
        }
    }

    /**
     * 获取一个转换器
     *
     * @param from
     *            源类型
     * @param to
     *            目标类型
     * @return 转换器
     */
    public <F, T> Castor<F, T> find(Class<F> from, Class<T> to) {
        return find(Mirror.me(from), to);
    }

    @SuppressWarnings("unchecked")
    private <F, T> Castor<F, T> find(Mirror<F> from, Class<T> toType) {
        String key = Castor.key(from.getType(), toType);
        // 哈，这种类型以前转过，直接返回转换器就行了
        if (map.containsKey(key)) {
            return (Castor<F, T>) map.get(key);
        }

        Mirror<T> to = Mirror.me(toType, extractor);
        Class<?>[] fets = from.extractTypes();
        Class<?>[] tets = to.extractTypes();
        for (Class<?> ft : fets) {
            for (Class<?> tt : tets) {
                if (map.containsKey(Castor.key(ft, tt))) {
                    String key2 = Castor.key(ft, tt);
                    Castor<F, T> castor = (Castor<F, T>) map.get(key2);
                    // 缓存转换器，加速下回转换速度
                    map.put(key, castor);
                    return castor;
                }
            }
        }
        return null;
    }

    /**
     * 转换一个 POJO 到另外的类型
     *
     * @param src
     *            源对象
     * @param toType
     *            目标类型
     * @return 目标对象
     * @throws FailToCastObjectException
     *             如果没有找到转换器，或者转换失败
     */
    public <T> T castTo(Object src, Class<T> toType) throws FailToCastObjectException {
        return cast(src, null == src ? null : src.getClass(), toType);
    }

    /**
     * 判断一个类型是否可以被转换成另外一个类型
     *

     * 判断的依据就是看是否可以直接被转型，以及能不能找到一个专有的转换器
     *
     * @param fromType
     *            起始类型
     * @param toType
     *            目标类型
     * @return 是否可以转换
     */
    public boolean canCast(Class<?> fromType, Class<?> toType) {
        if (Mirror.me(fromType).canCastToDirectly(toType))
            return true;

        if (toType.isArray() && toType.getComponentType().isAssignableFrom(fromType)) {
            return true;
        }

        Castor<?, ?> castor = this.find(fromType, toType);
        return !(castor instanceof Object2Object);
    }

    /**
     * 将一个 POJO 转换成字符串
     *
     * @param src
     *            源对象
     * @return 字符串
     */
    public String castToString(Object src) {
        try {
            return castTo(src, String.class);
        }
        catch (FailToCastObjectException e) {
            return String.valueOf(src);
        }
    }

    private static List<Class<?>> defaultCastorList = new ArrayList<Class<?>>(120);

    static {

        defaultCastorList.add(org.nutz.castor.castor.Array2Array.class);
        defaultCastorList.add(org.nutz.castor.castor.Array2Collection.class);
        defaultCastorList.add(org.nutz.castor.castor.Array2Map.class);
        defaultCastorList.add(org.nutz.castor.castor.Array2Object.class);
        defaultCastorList.add(org.nutz.castor.castor.Array2String.class);
        defaultCastorList.add(org.nutz.castor.castor.Boolean2Boolean.class);
        defaultCastorList.add(org.nutz.castor.castor.Boolean2Number.class);
        defaultCastorList.add(org.nutz.castor.castor.Boolean2String.class);
        defaultCastorList.add(org.nutz.castor.castor.Calendar2Datetime.class);
        defaultCastorList.add(org.nutz.castor.castor.Calendar2Long.class);
        defaultCastorList.add(org.nutz.castor.castor.Calendar2String.class);
        defaultCastorList.add(org.nutz.castor.castor.Calendar2Timestamp.class);
        defaultCastorList.add(org.nutz.castor.castor.Character2Number.class);
        defaultCastorList.add(org.nutz.castor.castor.Class2Mirror.class);
        defaultCastorList.add(org.nutz.castor.castor.Class2String.class);
        defaultCastorList.add(org.nutz.castor.castor.Collection2Array.class);
        defaultCastorList.add(org.nutz.castor.castor.Collection2Collection.class);
        defaultCastorList.add(org.nutz.castor.castor.Collection2Map.class);
        defaultCastorList.add(org.nutz.castor.castor.Collection2Object.class);
        defaultCastorList.add(org.nutz.castor.castor.Collection2String.class);
        defaultCastorList.add(org.nutz.castor.castor.Datetime2Calendar.class);
        defaultCastorList.add(org.nutz.castor.castor.Datetime2Long.class);
        defaultCastorList.add(org.nutz.castor.castor.Datetime2SqlDate.class);
        defaultCastorList.add(org.nutz.castor.castor.Datetime2SqlTime.class);
        defaultCastorList.add(org.nutz.castor.castor.Datetime2String.class);
        defaultCastorList.add(org.nutz.castor.castor.Datetime2Timpestamp.class);
        defaultCastorList.add(org.nutz.castor.castor.Enum2Number.class);
        defaultCastorList.add(org.nutz.castor.castor.Enum2String.class);
        defaultCastorList.add(org.nutz.castor.castor.File2String.class);
        defaultCastorList.add(org.nutz.castor.castor.Map2Array.class);
        defaultCastorList.add(org.nutz.castor.castor.Map2Boolean.class);
        defaultCastorList.add(org.nutz.castor.castor.Map2Collection.class);
        defaultCastorList.add(org.nutz.castor.castor.Map2Enum.class);
        defaultCastorList.add(org.nutz.castor.castor.Map2Object.class);
        defaultCastorList.add(org.nutz.castor.castor.Map2String.class);
        defaultCastorList.add(org.nutz.castor.castor.Mirror2Class.class);
        defaultCastorList.add(org.nutz.castor.castor.Mirror2String.class);
        defaultCastorList.add(org.nutz.castor.castor.Number2Boolean.class);
        defaultCastorList.add(org.nutz.castor.castor.Number2Byte.class);
        defaultCastorList.add(org.nutz.castor.castor.Number2Calendar.class);
        defaultCastorList.add(org.nutz.castor.castor.Number2Char.class);
        defaultCastorList.add(org.nutz.castor.castor.Number2Character.class);
        defaultCastorList.add(org.nutz.castor.castor.Number2Datetime.class);
        defaultCastorList.add(org.nutz.castor.castor.Number2Double.class);
        defaultCastorList.add(org.nutz.castor.castor.Number2Enum.class);
        defaultCastorList.add(org.nutz.castor.castor.Number2Float.class);
        defaultCastorList.add(org.nutz.castor.castor.Number2Integer.class);
        defaultCastorList.add(org.nutz.castor.castor.Number2Long.class);
        defaultCastorList.add(org.nutz.castor.castor.Number2Short.class);
        defaultCastorList.add(org.nutz.castor.castor.Number2String.class);
        defaultCastorList.add(org.nutz.castor.castor.Number2Timestamp.class);
        defaultCastorList.add(org.nutz.castor.castor.Object2Boolean.class);
        defaultCastorList.add(org.nutz.castor.castor.Object2Class.class);
        defaultCastorList.add(org.nutz.castor.castor.Object2List.class);
        defaultCastorList.add(org.nutz.castor.castor.Object2Map.class);
        defaultCastorList.add(org.nutz.castor.castor.Object2Mirror.class);
        defaultCastorList.add(org.nutz.castor.castor.Object2Object.class);
        defaultCastorList.add(org.nutz.castor.castor.Object2String.class);
        defaultCastorList.add(org.nutz.castor.castor.SqlDate2String.class);
        defaultCastorList.add(org.nutz.castor.castor.SqlDate2Timestamp.class);
        defaultCastorList.add(org.nutz.castor.castor.SqlTime2String.class);
        defaultCastorList.add(org.nutz.castor.castor.SqlTime2Timestamp.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Array.class);
        defaultCastorList.add(org.nutz.castor.castor.String2BigDecimal.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Boolean.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Byte.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Calendar.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Character.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Class.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Collection.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Datetime.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Double.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Email.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Enum.class);
        defaultCastorList.add(org.nutz.castor.castor.String2File.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Float.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Integer.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Long.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Map.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Mirror.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Object.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Pattern.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Set.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Short.class);
        defaultCastorList.add(org.nutz.castor.castor.String2SqlDate.class);
        defaultCastorList.add(org.nutz.castor.castor.String2SqlTime.class);
        defaultCastorList.add(org.nutz.castor.castor.String2TimeZone.class);
        defaultCastorList.add(org.nutz.castor.castor.String2Timestamp.class);
        defaultCastorList.add(org.nutz.castor.castor.TimeZone2String.class);
        defaultCastorList.add(org.nutz.castor.castor.Timestamp2Calendar.class);
        defaultCastorList.add(org.nutz.castor.castor.Timestamp2Datetime.class);
        defaultCastorList.add(org.nutz.castor.castor.Timestamp2Long.class);
        defaultCastorList.add(org.nutz.castor.castor.Timestamp2SqlDate.class);
        defaultCastorList.add(org.nutz.castor.castor.Timestamp2SqlTime.class);
        defaultCastorList.add(org.nutz.castor.castor.Timestamp2String.class);
        defaultCastorList.add(org.nutz.castor.castor.String2DateFormat.class);

        defaultCastorList.add(org.nutz.castor.castor.String2TmInfo.class);
        defaultCastorList.add(org.nutz.castor.castor.Integer2TmInfo.class);
        defaultCastorList.add(org.nutz.castor.castor.Long2TmInfo.class);
        defaultCastorList.add(org.nutz.castor.castor.TmInfo2String.class);
        defaultCastorList.add(org.nutz.castor.castor.TmInfo2Long.class);
        defaultCastorList.add(org.nutz.castor.castor.TmInfo2Integer.class);

        if (NutConf.HAS_LOCAL_DATE_TIME) {
            defaultCastorList.add(org.nutz.castor.castor.String2LocalDateTime.class);
            defaultCastorList.add(org.nutz.castor.castor.String2LocalTime.class);
            defaultCastorList.add(org.nutz.castor.castor.String2LocalDate.class);
            defaultCastorList.add(org.nutz.castor.castor.LocalDate2String.class);
            defaultCastorList.add(org.nutz.castor.castor.LocalTime2String.class);
            defaultCastorList.add(org.nutz.castor.castor.LocalDateTime2String.class);
        }
    }

    private static Castors one = new Castors();
}