package com.googlecode.mycontainer.commons.servlet.json;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.googlecode.mycontainer.commons.json.JsonHandler;
import com.googlecode.mycontainer.commons.reflect.ObjectReflect;
public class JsonInvoker {
private static enum InvokeType {
NORMAL, HARD, HARDEST;
}
private final Object obj;
public JsonInvoker(Object obj) {
this.obj = obj;
}
public void invoke(HttpServletRequest req, HttpServletResponse resp,
FilterChain chain, String method, String... args) {
try {
invokeInternal(req, resp, chain, method, InvokeType.NORMAL, args);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
public void hardInvoke(HttpServletRequest req, HttpServletResponse resp,
FilterChain chain, String method, String... args) throws Throwable {
invokeInternal(req, resp, chain, method, InvokeType.HARD, args);
}
public void hardestInvoke(HttpServletRequest req, HttpServletResponse resp,
FilterChain chain, String method, String... args)
throws IllegalAccessException, InvocationTargetException,
IllegalArgumentException {
try {
invokeInternal(req, resp, chain, method, InvokeType.HARDEST, args);
} catch (IllegalArgumentException e) {
throw e;
} catch (IllegalAccessException e) {
throw e;
} catch (InvocationTargetException e) {
throw e;
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
private void invokeInternal(HttpServletRequest req,
HttpServletResponse resp, FilterChain chain, String method,
InvokeType invokeType, String... args) throws Throwable {
ObjectReflect reflect = new ObjectReflect(obj);
Method m = reflect.findMethod(method, new Class<?>[]{
HttpServletRequest.class, HttpServletResponse.class,
FilterChain.class});
if (m == null) {
m = reflect.findMethod(method, new Class<?>[]{
HttpServletRequest.class, HttpServletResponse.class});
}
if (m == null) {
m = reflect.findMethod(method,
new Class<?>[]{HttpServletRequest.class});
}
Object ret = null;
if (m != null) {
Object[] values = new Object[m.getParameterTypes().length];
values[0] = req;
if (m.getParameterTypes().length > 1) {
values[1] = resp;
}
if (m.getParameterTypes().length > 2) {
values[2] = chain;
}
ret = reflect.invoke(m, values);
if (m.getParameterTypes().length > 1) {
return;
}
} else {
if (args == null) {
args = new String[0];
}
int size = args.length;
m = reflect.findMethod(method, size);
if (m == null) {
throw new RuntimeException("method not found: " + method
+ " with " + size + " arguments");
}
List<Object> params = parseParameters(args, m.getParameterTypes());
ret = invoke(reflect, m, params, invokeType);
}
try {
PrintWriter writer = resp.getWriter();
JsonHandler.instance().format(ret, writer);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public Object invoke(ObjectReflect reflect, Method m, List<Object> params,
InvokeType invokeType) throws Throwable {
Object[] args = params.toArray(new Object[params.size()]);
switch (invokeType) {
case NORMAL :
return reflect.invoke(m, args);
case HARD :
return reflect.hardInvoke(m, args);
case HARDEST :
return reflect.hardestInvoke(m, args);
}
throw new IllegalArgumentException();
}
private List<Object> parseParameters(String[] values, Class<?>[] types) {
List<Object> ret = new ArrayList<Object>();
for (int i = 0; i < types.length; i++) {
Class<?> type = types[i];
String value = values[i];
Object obj = JsonHandler.instance().parse(value, type);
ret.add(obj);
}
return ret;
}
}