package org.ccpit.base.utils;

/**
 * Created by Administrator on 2015/8/13.
 */

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.ccpit.base.modol.EscapeSql;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Html 标签过滤工具，防止js注入
 * 只对String类型的字段进行过滤
 * Created by Sunqipeng on 2015/7/24.
 */
public class SqlEscapeUtil<T> {

    /**
     * 实体
     */
    private T entry;
    /**
     * 排除的字段
     */
    private List<String> escapes = new ArrayList<String>();

    /**
     * 添加要排除的字段
     *
     * @param propertyName
     * @return
     */
    public SqlEscapeUtil<T> except(String propertyName) {
        escapes.add(propertyName);
        return this;
    }

    /**
     * 添加多个排除的字段
     *
     * @param propertyNames
     * @return
     */
    public SqlEscapeUtil<T> except(String... propertyNames) {
        escapes.addAll(Arrays.asList(propertyNames));
        return this;
    }

    /**
     * 设置要过滤的实体
     *
     * @param entry
     * @return
     */
    public SqlEscapeUtil<T> encode(T entry) {
        this.entry = entry;
        return this;
    }

    /**
     * 执行过滤操作
     *
     * @return
     */
    public T execute() {
        if (entry == null)
            return null;

        Field[] fields = entry.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field f = fields[i];
            String name = f.getName();
            if (escapes.contains(name))
                continue;

            if (f.getType().isAssignableFrom(String.class)) {
                String upName = name.replaceFirst(name.substring(0, 1), name.substring(0, 1).toUpperCase());
                try {
                    Method method = entry.getClass().getMethod("get" + upName);
                    String value = (String) method.invoke(entry);
                    if (!StringUtils.isEmpty(value)) {
                        value = escapeSql(value);
                        Method setter = entry.getClass().getMethod("set" + upName, String.class);
                        setter.invoke(entry, value);
                    }
                } catch (NoSuchMethodException e) {
                    System.out.println("未找到方法：" + upName);
                    continue;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return entry;
    }

    /**
     * Escape the Sql with the annotation
     * @param t
     * @return
     */
    public T escape(T t){
        EscapeSql annotation = t.getClass().getAnnotation(EscapeSql.class);
        if (annotation!=null){
            encode(t);
            except(annotation.except());
            execute();
        }
        return t;
    }
    /**
     * 过滤方法
     *
     * @param prop
     * @return
     */
    public static String escapeSql(String prop) {
        prop = StringEscapeUtils.escapeSql(prop);
        return prop;
    }
}
