package net.mengkang.nettyrest;
import io.netty.channel.ChannelHandlerContext;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* connect netty server and api resource
*
*/
public class ApiHandler {
private static final Logger logger = LoggerFactory.getLogger(ApiHandler.class);
/**
* api data I/O port
*
* @param ctx
* @param msg
* @return
*/
public static byte[] transfer(ChannelHandlerContext ctx, Object msg) {
ApiProtocol apiProtocol = new ApiProtocol(ctx, msg);
if (apiProtocol.getEndpoint() == null) {
return encode(ErrorHandler.error(StatusCode.API_CAN_NOT_BE_NULL));
}
if (apiProtocol.getApi() == null) {
return encode(ErrorHandler.error(StatusCode.API_NOT_FOUND));
}
Object result = invoke(apiProtocol.getApi(), apiProtocol);
if (result == null) {
return encode(ErrorHandler.error(StatusCode.UNKNOWN_ERROR));
}
return encode(result);
}
/**
* invoke api resource method by apiName, but the request apiProtocol should observe routeMap regulations
*
* @param apiName
* @param apiProtocol
* @return
*/
public static Object invoke(String apiName, ApiProtocol apiProtocol) {
Class<?> classname;
Object classObject;
Constructor constructor;
Method method;
Object result = null;
Api api = ApiRoute.apiMap.get(apiName);
if (api == null) {
return ErrorHandler.error(StatusCode.API_NOT_FOUND);
}
if (apiProtocol.getBuild() < api.getBuild()){
return ErrorHandler.error(StatusCode.VERSION_IS_TOO_LOW);
}
if(api.getHttpMethod() != null && !api.getHttpMethod().contains(apiProtocol.getMethod().toString().toLowerCase())){
return ErrorHandler.error(StatusCode.REQUEST_MODE_ERROR);
}
try {
classname = Class.forName(Config.getString("resource.package.name") + "." + api.getResource());
constructor = classname.getConstructor(ApiProtocol.class);
classObject = constructor.newInstance(apiProtocol);
} catch (NoSuchMethodException e) {
logger.error(e.getMessage());
return ErrorHandler.error(StatusCode.API_SERVER_ERROR);
} catch (ClassNotFoundException e) {
logger.error(e.getMessage());
return ErrorHandler.error(StatusCode.API_SERVER_ERROR);
} catch (InvocationTargetException e) {
logger.error(e.getMessage());
return ErrorHandler.error(StatusCode.API_SERVER_ERROR);
} catch (InstantiationException e) {
logger.error(e.getMessage());
return ErrorHandler.error(StatusCode.API_SERVER_ERROR);
} catch (IllegalAccessException e) {
logger.error(e.getMessage());
return ErrorHandler.error(StatusCode.API_SERVER_ERROR);
}
try {
method = classname.getMethod(apiProtocol.getMethod().toString().toLowerCase());
} catch (NoSuchMethodException e) {
logger.error(e.getMessage());
return ErrorHandler.error(StatusCode.API_SERVER_ERROR);
}
try {
result = method.invoke(classObject);
} catch (InvocationTargetException e) {
e.printStackTrace();
logger.error(e.getMessage());
} catch (IllegalAccessException e) {
logger.error(e.toString());
}
return result;
}
/**
* exchange the api resource returns to a JSONObject
*
* @param object
* @return
*/
public static byte[] encode(Object object) {
String data = new JSONObject(object).toString();
data = filter(data);
return data.getBytes();
}
/**
* we always need filter something for some reason,
* otherwise we can replace the timestamp to the string we defined, and so on.
*
* @param data
* @return
*/
public static String filter(String data){
return data;
}
}