
com.github.kubatatami.judonetworking.RequestProxy Maven / Gradle / Ivy
package com.github.kubatatami.judonetworking;
import android.util.Pair;
import com.github.kubatatami.judonetworking.exceptions.JudoException;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.RejectedExecutionException;
class RequestProxy implements InvocationHandler {
protected final EndpointImplementation rpc;
protected int id = 0;
protected boolean batch = false;
protected boolean batchFatal = true;
protected final List batchRequests = new ArrayList();
protected BatchMode mode = BatchMode.NONE;
protected Map annotations;
public RequestProxy(EndpointImplementation rpc, Class> apiInterface, BatchMode mode) {
this.rpc = rpc;
this.mode = mode;
batch = (mode == BatchMode.MANUAL);
Method[] methods = apiInterface.getMethods();
annotations = new HashMap(methods.length);
for (Method method : methods) {
annotations.put(method, method.getAnnotation(RequestMethod.class));
}
}
protected final Runnable batchRunnable = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(rpc.getProtocolController().getAutoBatchTime());
} catch (InterruptedException e) {
e.printStackTrace();
}
callBatch(null);
}
};
public void setBatchFatal(boolean batchFatal) {
this.batchFatal = batchFatal;
}
public static String getMethodName(Method method, RequestMethod ann) {
NamePrefix namePrefix = method.getDeclaringClass().getAnnotation(NamePrefix.class);
String name = (ann != null && !ann.name().equals("")) ? ann.name() : method.getName();
if(namePrefix!=null){
name=namePrefix.value()+name;
}
return name;
}
public static StackTraceElement getExternalStacktrace(StackTraceElement[] stackTrace) {
String packageName = RequestProxy.class.getPackage().getName();
boolean current = false;
for (StackTraceElement element : stackTrace) {
if (!current && element.getClassName().contains(packageName)) {
current = true;
} else if (current && !element.getClassName().contains(packageName) && !element.getClassName().contains("$Proxy")) {
return element;
}
}
return stackTrace[0];
}
protected Object performAsyncRequest(Method m, Object[] args, String name, int timeout, RequestMethod ann) throws Exception {
final Request request = callAsync(++id, m, name, args, m.getGenericParameterTypes(), timeout, ann);
synchronized (batchRequests) {
if (batch) {
request.setBatchFatal(batchFatal);
batchRequests.add(request);
batch = true;
return null;
} else {
if (mode == BatchMode.AUTO) {
batchRequests.add(request);
batch = true;
try{
rpc.getExecutorService().execute(batchRunnable);
}catch (RejectedExecutionException ex){
for(Request batchRequest : batchRequests){
new AsyncResult(batchRequest.getCallback(),new JudoException("Request queue is full.",ex)).run();
}
}
return null;
} else {
try{
rpc.getExecutorService().execute(request);
}catch (RejectedExecutionException ex){
new AsyncResult(request.getCallback(),new JudoException("Request queue is full.",ex)).run();
}
return null;
}
}
}
}
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
try {
RequestMethod ann = annotations.get(m);
if (ann != null) {
String name = getMethodName(m, ann);
int timeout = rpc.getRequestConnector().getMethodTimeout();
if ((rpc.getDebugFlags() & Endpoint.REQUEST_LINE_DEBUG) > 0) {
try {
StackTraceElement stackTraceElement = getExternalStacktrace(Thread.currentThread().getStackTrace());
if (batch && mode == BatchMode.MANUAL) {
LoggerImpl.log("Batch request " + name + " from " +
stackTraceElement.getClassName() +
"(" + stackTraceElement.getFileName() + ":" + stackTraceElement.getLineNumber() + ")");
} else {
LoggerImpl.log("Request " + name + " from " +
stackTraceElement.getClassName() +
"(" + stackTraceElement.getFileName() + ":" + stackTraceElement.getLineNumber() + ")");
}
} catch (Exception ex) {
LoggerImpl.log("Can't log stacktrace");
}
}
if (ann.timeout() != 0) {
timeout = ann.timeout();
}
if (!ann.async()) {
Object additionalData = rpc.getProtocolController().getAdditionalRequestData();
Request request = new Request(++id, rpc, m, name, ann, args, m.getReturnType(), timeout, null, additionalData);
return rpc.getRequestConnector().call(request);
} else {
return performAsyncRequest(m, args, name, timeout, ann);
}
} else {
try {
return m.invoke(this, args);
} catch (IllegalArgumentException e) {
throw new JudoException("No @RequestMethod on " + m.getName());
}
}
} catch (Exception e) {
if (rpc.getErrorLogger() != null) {
rpc.getErrorLogger().onError(e);
}
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
protected Request callAsync(int id, Method m, String name, Object[] args, Type[] types, int timeout, RequestMethod ann) throws Exception {
Object[] newArgs = args;
CallbackInterface
© 2015 - 2025 Weber Informatics LLC | Privacy Policy