package com.dianping.pigeon.remoting.invoker.util;
import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.Future;
import com.dianping.pigeon.log.Logger;
import com.dianping.pigeon.log.LoggerLoader;
import com.dianping.pigeon.remoting.common.codec.SerializerFactory;
import com.dianping.pigeon.remoting.common.codec.SerializerType;
import com.dianping.pigeon.remoting.common.domain.InvocationRequest;
import com.dianping.pigeon.remoting.common.domain.InvocationResponse;
import com.dianping.pigeon.remoting.common.channel.Channel;
import com.dianping.pigeon.remoting.common.domain.generic.GenericRequest;
import com.dianping.pigeon.remoting.common.exception.ApplicationException;
import com.dianping.pigeon.remoting.common.exception.NetworkException;
import com.dianping.pigeon.remoting.common.exception.RpcException;
import com.dianping.pigeon.remoting.common.util.Constants;
import com.dianping.pigeon.remoting.common.util.InvocationUtils;
import com.dianping.pigeon.remoting.invoker.Client;
import com.dianping.pigeon.remoting.invoker.concurrent.Callback;
import com.dianping.pigeon.remoting.invoker.config.InvokerConfig;
import com.dianping.pigeon.remoting.invoker.domain.InvokerContext;
import com.dianping.pigeon.remoting.invoker.domain.RemoteInvocationBean;
import com.dianping.pigeon.remoting.invoker.exception.RemoteInvocationException;
import com.dianping.pigeon.remoting.invoker.service.ServiceInvocationRepository;
public class InvokerUtils {
private static ServiceInvocationRepository invocationRepository = ServiceInvocationRepository.getInstance();
private static final Logger logger = LoggerLoader.getLogger(InvokerUtils.class);
public static InvocationResponse sendRequest(Client client, InvocationRequest request, Callback callback) {
if (request.getCallType() == Constants.CALLTYPE_REPLY) {
RemoteInvocationBean invocationBean = new RemoteInvocationBean();
invocationBean.request = request;
invocationBean.callback = callback;
callback.setRequest(request);
callback.setClient(client);
invocationRepository.put(request.getSequence(), invocationBean);
}
InvocationResponse response = null;
try {
response = client.write(request);
} catch (NetworkException e) {
invocationRepository.remove(request.getSequence());
logger.warn("network exception ocurred:" + request, e);
throw e;
} finally {
if (response != null) {
invocationRepository.remove(request.getSequence());
}
}
return response;
}
public static void sendRequest(Client client, Channel channel, InvocationRequest request, Callback callback) {
if (request.getCallType() == Constants.CALLTYPE_REPLY) {
RemoteInvocationBean invocationBean = new RemoteInvocationBean();
invocationBean.request = request;
invocationBean.callback = callback;
callback.setRequest(request);
callback.setClient(client);
invocationRepository.put(request.getSequence(), invocationBean);
}
try {
channel.write(request);
} catch (NetworkException e) {
invocationRepository.remove(request.getSequence());
logger.warn("network exception ocurred:" + request, e);
throw e;
}
}
public static InvocationRequest createRemoteCallRequest(InvokerContext invokerContext,
InvokerConfig<?> invokerConfig) {
InvocationRequest request = invokerContext.getRequest();
if (request == null) {
request = SerializerFactory.getSerializer(invokerConfig.getSerialize()).newRequest(invokerContext);
invokerContext.setRequest(request);
}
return request;
}
public static InvocationResponse createNoReturnResponse() {
return new NoReturnResponse();
}
public static InvocationResponse createDefaultResponse(Object defaultResult) {
return new NoReturnResponse(defaultResult);
}
public static InvocationResponse createThrowableResponse(Throwable e) {
InvocationResponse response = new NoReturnResponse(e);
response.setMessageType(Constants.MESSAGE_TYPE_EXCEPTION);
return response;
}
public static InvocationResponse createFutureResponse(Future serviceFuture) {
FutureResponse resp = new FutureResponse();
resp.setServiceFuture(serviceFuture);
return resp;
}
public static boolean isHeartErrorResponse(InvocationResponse response) {
return response != null && response.getMessageType() == Constants.MESSAGE_TYPE_HEART
&& response.getCause() != null;
}
public static RuntimeException toApplicationRuntimeException(InvocationResponse response) {
Throwable t = toApplicationException(response);
if (t instanceof RuntimeException) {
return (RuntimeException) t;
} else {
return new ApplicationException(t);
}
}
public static Exception toApplicationException(InvocationResponse response) {
Object responseReturn = response.getReturn();
if (responseReturn == null) {
return new ApplicationException(response.getCause());
} else if (responseReturn instanceof RpcException) {
return new ApplicationException((RpcException) responseReturn);
} else if (responseReturn instanceof Exception) {
return (Exception) responseReturn;
} else if (responseReturn instanceof Throwable) {
return new RemoteInvocationException((Throwable) responseReturn);
} else if (responseReturn instanceof Map) {
Map errors = (Map) responseReturn;
String detailMessage = (String) errors.get("detailMessage");
StackTraceElement[] stackTrace = (StackTraceElement[]) errors.get("stackTrace");
ApplicationException e = new ApplicationException(detailMessage);
e.setStackTrace(stackTrace);
return e;
} else {
return new ApplicationException(responseReturn.toString());
}
}
public static RpcException toRpcException(InvocationResponse response) {
Throwable e = null;
Object responseReturn = response.getReturn();
if (responseReturn == null) {
return new RemoteInvocationException(response.getCause());
} else if (responseReturn instanceof Throwable) {
e = (Throwable) responseReturn;
} else if (responseReturn instanceof Map) {
Map errors = (Map) responseReturn;
String detailMessage = (String) errors.get("detailMessage");
StackTraceElement[] stackTrace = (StackTraceElement[]) errors.get("stackTrace");
e = new RemoteInvocationException(detailMessage);
e.setStackTrace(stackTrace);
} else {
e = new RemoteInvocationException(responseReturn.toString());
}
if (!(e instanceof RpcException)) {
return new RemoteInvocationException(e);
}
return (RpcException) e;
}
static class NoReturnResponse implements InvocationResponse {
/**
* serialVersionUID
*/
private static final long serialVersionUID = 4348389641787057819L;
private long invokerRequestTime;
private long invokerResponseTime;
private long providerRequestTime;
private long providerResponseTime;
private Object result;
private int messageType = Constants.MESSAGE_TYPE_SERVICE;
public NoReturnResponse() {
}
public NoReturnResponse(Object defaultResult) {
this.result = defaultResult;
}
public long getInvokerRequestTime() {
return invokerRequestTime;
}
public void setInvokerRequestTime(long invokerRequestTime) {
this.invokerRequestTime = invokerRequestTime;
}
public long getInvokerResponseTime() {
return invokerResponseTime;
}
public void setInvokerResponseTime(long invokerResponseTime) {
this.invokerResponseTime = invokerResponseTime;
}
public long getProviderRequestTime() {
return providerRequestTime;
}
public void setProviderRequestTime(long providerRequestTime) {
this.providerRequestTime = providerRequestTime;
}
public long getProviderResponseTime() {
return providerResponseTime;
}
public void setProviderResponseTime(long providerResponseTime) {
this.providerResponseTime = providerResponseTime;
}
@Override
public void setMessageType(int messageType) {
this.messageType = messageType;
}
@Override
public int getMessageType() {
return messageType;
}
@Override
public String getCause() {
return null;
}
@Override
public Object getReturn() {
return result;
}
@Override
public void setReturn(Object obj) {
}
@Override
public byte getSerialize() {
return 0;
}
@Override
public void setSequence(long seq) {
}
@Override
public long getSequence() {
return 0;
}
@Override
public Object getContext() {
return null;
}
@Override
public void setContext(Object context) {
}
@Override
public void setSerialize(byte serialize) {
}
@Override
public void setSize(int size) {
}
@Override
public int getSize() {
return 0;
}
@Override
public Map<String, Serializable> getResponseValues() {
return null;
}
@Override
public void setResponseValues(Map<String, Serializable> responseValues) {
}
@Override
public long getCreateMillisTime() {
return 0;
}
@Override
public void setCreateMillisTime(long createMillisTime) {
}
}
public static class FutureResponse implements InvocationResponse {
/**
* serialVersionUID
*/
private static final long serialVersionUID = 4348389641787057819L;
private long invokerRequestTime;
private long invokerResponseTime;
private long providerRequestTime;
private long providerResponseTime;
private Future serviceFuture;
public Future getServiceFuture() {
return serviceFuture;
}
public void setServiceFuture(Future serviceFuture) {
this.serviceFuture = serviceFuture;
}
public long getInvokerRequestTime() {
return invokerRequestTime;
}
public void setInvokerRequestTime(long invokerRequestTime) {
this.invokerRequestTime = invokerRequestTime;
}
public long getInvokerResponseTime() {
return invokerResponseTime;
}
public void setInvokerResponseTime(long invokerResponseTime) {
this.invokerResponseTime = invokerResponseTime;
}
public long getProviderRequestTime() {
return providerRequestTime;
}
public void setProviderRequestTime(long providerRequestTime) {
this.providerRequestTime = providerRequestTime;
}
public long getProviderResponseTime() {
return providerResponseTime;
}
public void setProviderResponseTime(long providerResponseTime) {
this.providerResponseTime = providerResponseTime;
}
@Override
public void setMessageType(int messageType) {
}
@Override
public int getMessageType() {
return Constants.MESSAGE_TYPE_SERVICE;
}
@Override
public String getCause() {
return null;
}
@Override
public Object getReturn() {
return null;
}
@Override
public void setReturn(Object obj) {
}
@Override
public byte getSerialize() {
return 0;
}
@Override
public void setSequence(long seq) {
}
@Override
public long getSequence() {
return 0;
}
@Override
public Object getContext() {
return null;
}
@Override
public void setContext(Object context) {
}
@Override
public void setSerialize(byte serialize) {
}
@Override
public void setSize(int size) {
}
@Override
public int getSize() {
return 0;
}
@Override
public Map<String, Serializable> getResponseValues() {
return null;
}
@Override
public void setResponseValues(Map<String, Serializable> responseValues) {
}
@Override
public long getCreateMillisTime() {
return 0;
}
@Override
public void setCreateMillisTime(long createMillisTime) {
}
}
}