package net.ion.craken.db; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; import java.util.Map; import net.ion.craken.node.ReadSession; import net.ion.craken.node.Repository; import net.ion.framework.db.Rows; import net.ion.framework.db.procedure.UserProcedure; import net.ion.framework.util.ArrayUtil; import net.ion.framework.util.ListUtil; import net.ion.framework.util.MapUtil; import net.ion.framework.util.StringUtil; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import org.apache.commons.beanutils.MethodUtils; import org.apache.lucene.index.CorruptIndexException; public class CrakenFnManager extends CrakenManager { private Repository repository; private String wname ; public CrakenFnManager(Repository repository, String wname) { super() ; this.repository = repository; this.wname = wname ; } private Map<String, QueryPackage> packages = MapUtil.newMap(); public int updateWith(CrakenUserProcedureBatch batch) throws Exception{ Object result = callFunction(batch); if (result == null) return 0; if (result instanceof Integer) return ((Integer) result).intValue(); return -1; } public int updateWith(CrakenUserProcedure cupt) throws Exception { Object result = callFunction(cupt); if (result == null) return 0; if (result instanceof Integer) return ((Integer) result).intValue(); return -1; } @Override public int updateWith(CrakenUserProcedures cupts) throws Exception { throw new UnsupportedOperationException("if you must do it, call bleujin") ; } private Object callFunction(UserProcedure cupt) throws SecurityException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, IllegalArgumentException, CorruptIndexException, IOException { String packageName = StringUtil.substringBefore(cupt.getProcName(), "@"); String functionName = StringUtil.substringAfter(cupt.getProcName(), "@"); QueryPackage targetPackage = packages.get(packageName); if (targetPackage == null) throw new IllegalArgumentException("not found package : " + packageName); final Field field = targetPackage.getClass().getSuperclass().getDeclaredField("session"); field.setAccessible(true); field.set(targetPackage, session()); // BeanUtils.setProperty(targetPackage, "session", session()) ; Method[] mts = targetPackage.getClass().getMethods(); final Object[] params = cupt.getParams().toArray(); for (Method method : mts) { if (method.isAnnotationPresent(Function.class) && functionName.equalsIgnoreCase(method.getAnnotation(Function.class).value())) { final Class<?>[] paramTypes = method.getParameterTypes(); return MethodUtils.invokeMethod(targetPackage, method.getName(), handlePrimitive(params, paramTypes), paramTypes); } ; } for (Method method : mts) { // if not found annotation if (method.getName().equalsIgnoreCase(functionName)) { final Class<?>[] paramTypes = method.getParameterTypes(); return MethodUtils.invokeMethod(targetPackage, method.getName(), handlePrimitive(params, paramTypes), paramTypes); } } throw new IllegalArgumentException("not found function : " + functionName); } private Object[] handlePrimitive(Object[] params, Class<?>[] paramTypes) { List<Object> result = ListUtil.newList() ; for (int i = 0 ; i < params.length ; i++) { Object param = params[i] ; Class paramType = paramTypes[i] ; if (paramType.isArray() && paramType.getComponentType().isPrimitive()){ result.add(getPrimitiveArray(param)) ; } else { result.add(param) ; } } return result.toArray() ; } private Object getPrimitiveArray(Object val) { if (val instanceof Integer[]) return ArrayUtil.toPrimitive((Integer[])val) ; if (val instanceof Boolean[]) return ArrayUtil.toPrimitive((Boolean[])val) ; if (val instanceof Long[]) return ArrayUtil.toPrimitive((Long[])val) ; return (Object[]) val; } public Rows queryBy(CrakenUserProcedure cupt) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, CorruptIndexException, IOException { Object result = callFunction(cupt); if (result == null || (!Rows.class.isInstance(result))) throw new IllegalStateException("returnType must be rows"); return (Rows) result; } public ReadSession session() throws IOException { return repository.login(wname); } public CrakenFnManager register(String packageName, QueryPackage queryPackage) { packages.put(packageName, queryPackage); return this; } } class ConnectionMock implements MethodInterceptor { @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy arg3) throws Throwable { return null; // throw new IllegalStateException("this is fake object") ; } }