package com.taobao.easyweb.core.groovy;
import com.taobao.easyweb.core.app.App;
import com.taobao.easyweb.core.context.ThreadContext;
import com.taobao.easyweb.core.groovy.groovyobject.GroovyObjectLoader;
import com.taobao.easyweb.core.request.Param;
import com.taobao.easyweb.core.request.RequestBean;
import groovy.lang.GroovyObject;
import org.apache.commons.lang.StringUtils;
import org.codehaus.groovy.reflection.CachedMethod;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component("ewGroovyEngine")
public class GroovyEngine {
/**
* ÿ��������Ӧ�IJ�����
*/
private static Map<String, Map<String, Integer>> scriptMethods = new ConcurrentHashMap<String, Map<String, Integer>>();
@Resource
private GroovyObjectLoader groovyObjectLoader;
public static void putScriptMethod(String file, String method, Integer size) {
Map<String, Integer> methods = scriptMethods.get(file);
if (methods == null) {
methods = new HashMap<String, Integer>();
scriptMethods.put(file, methods);
}
scriptMethods.get(file).put(method, size);
}
public Object execute(File file, String method) throws Exception {
App app = ThreadContext.getContext().getApp();
GroovyObject groovyObject = groovyObjectLoader.getObject(true, app, file);
return groovyObject.invokeMethod(method, setParameters(groovyObject, method, file));
}
private Object[] setParameters(GroovyObject groovyObject, String method, File file) throws Exception {
Map<String, Integer> methods = scriptMethods.get(file.getAbsolutePath());
if (methods == null) {//����Groovy class��compile��ʱ���ȡ���Է�����Ϣ��������ʱֻ֧���η�������
return new Object[0];
}
int size = methods.get(method) == null ? 0 : methods.get(method);
if (size == 0) {
return new Object[0];
}
groovy.lang.MetaMethod metaMethod = groovyObject.getMetaClass().getMetaMethod(method, new Object[size]);
Method javaMethod = ((CachedMethod) metaMethod).getCachedMethod();
// Page page = javaMethod.getAnnotation(Page.class);
// if (page == null) {
// return new Object[size];
// }
Type[] paramTypes = javaMethod.getGenericParameterTypes();
Annotation[][] paramAnnotations = javaMethod.getParameterAnnotations();
Object[] params = new Object[paramTypes.length];
if (paramTypes.length != paramAnnotations.length) {
throw new Exception("������ʽ����");
}
if (paramTypes.length == 0) {
return params;
}
for (int i = 0; i < paramTypes.length; i++) {
Annotation annotation = paramAnnotations[i][0];
if (annotation instanceof Param) {
params[i] = typeCovert((Param) annotation, paramTypes[i]);
} else if (annotation instanceof RequestBean) {
params[i] = beanConvert(paramTypes[i]);
}
}
return params;
}
private Object typeCovert(Param param, Type type) {
String name = param.name();
if (StringUtils.isBlank(name)) {
name = param.value();
}
if (type instanceof Class<?>) {
Class<?> clazz = (Class<?>) type;
if (clazz.isArray()) {
Class<?> componentClazz = clazz.getComponentType();
String[] values = ThreadContext.getContext().getRequest().getParameterValues(name);
if (values != null) {
Object array = Array.newInstance(componentClazz, values.length);
for (int i = 0; i < values.length; i++) {
Array.set(array, i, convert(param, values[i], componentClazz));
}
return array;
}
return null;
} else {
String value = ThreadContext.getContext().getRequest().getParameter(name);
return convert(param, value, clazz);
}
}
return null;
}
private Object convert(Param param, String value, Class<?> clazz) {
if (clazz.equals(Integer.class) || clazz.equals(Integer.TYPE)) {
try {
return Integer.valueOf(value);
} catch (Throwable e) {
if (StringUtils.isNotBlank(param.defaultValue())) {
return Integer.valueOf(param.defaultValue());
}
}
} else if (clazz.equals(Long.class) || clazz.equals(Long.TYPE)) {
try {
return Long.valueOf(value);
} catch (Throwable e) {
if (StringUtils.isNotBlank(param.defaultValue())) {
return Long.valueOf(param.defaultValue());
}
}
} else if (clazz.equals(Double.class) || clazz.equals(Double.TYPE)) {
try {
return Double.valueOf(value);
} catch (Throwable e) {
if (StringUtils.isNotBlank(param.defaultValue())) {
return Double.valueOf(param.defaultValue());
}
}
} else if (clazz.equals(Float.class) || clazz.equals(Float.TYPE)) {
try {
return Float.valueOf(value);
} catch (Throwable e) {
if (StringUtils.isNotBlank(param.defaultValue())) {
return Float.valueOf(param.defaultValue());
}
}
} else if (clazz.equals(Boolean.class) || clazz.equals(Boolean.TYPE)) {
try {
return Boolean.valueOf(value);
} catch (Throwable e) {
if (StringUtils.isNotBlank(param.defaultValue())) {
return Boolean.valueOf(param.defaultValue());
}
}
} else {
if (value != null) {
return value;
} else if (StringUtils.isNotBlank(param.defaultValue())) {
return param.defaultValue();
}
}
return null;
}
private Object beanConvert(Type beanType) {
if (beanType instanceof Class<?>) {
Class<?> clazz = (Class<?>) beanType;
try {
Object bean = clazz.newInstance();
Field[] fields = clazz.getDeclaredFields();
for (Field it : fields) {
it.setAccessible(true);
String name = it.getName();
Class<?> type = it.getType();
String requestValue = ThreadContext.getContext().getRequest().getParameter(name);
if (requestValue != null) {
Object propertyValue = null;
if (type.equals(Integer.class) || type.equals(Integer.TYPE)) {
try {
propertyValue = Integer.valueOf(requestValue);
} catch (Exception e) {
// ���Ϸ�����������װ
}
} else if (type.equals(Long.class) || type.equals(Long.TYPE)) {
try {
propertyValue = Long.valueOf(requestValue);
} catch (Exception e) {
// ���Ϸ�����������װ
}
} else if (type.equals(Double.class) || type.equals(Double.TYPE)) {
try {
propertyValue = Double.valueOf(requestValue);
} catch (Exception e) {
// ���Ϸ�����������װ
}
} else if (type.equals(Float.class) || type.equals(Float.TYPE)) {
try {
propertyValue = Float.valueOf(requestValue);
} catch (Exception e) {
// ���Ϸ�����������װ
}
} else if (type.equals(Boolean.class) || type.equals(Boolean.TYPE)) {
try {
propertyValue = Boolean.valueOf(requestValue);
} catch (Exception e) {
// ���Ϸ�����������װ
}
} else {
propertyValue = requestValue;
}
if (propertyValue != null) {
it.set(bean, propertyValue);
}
}
}
return bean;
} catch (InstantiationException e) {
return null;
} catch (IllegalAccessException e) {
return null;
}
}
return null;
}
}