package com.jiuqi.mobile.nigo.comeclose.ws.client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import javax.xml.crypto.dsig.keyinfo.RetrievalMethod;
import org.apache.log4j.xml.Log4jEntityResolver;
import com.jiuqi.mobile.nigo.comeclose.exception.ConnectServiceFailException;
import com.jiuqi.mobile.nigo.comeclose.exception.NiGoException;
import com.jiuqi.mobile.nigo.comeclose.exception.WSFailException;
import com.jiuqi.mobile.nigo.comeclose.exception.WSRequestErrorException;
import com.jiuqi.mobile.nigo.comeclose.json.JSONArray;
import com.jiuqi.mobile.nigo.comeclose.json.JSONConvertor2;
import com.jiuqi.mobile.nigo.comeclose.json.JSONException;
import com.jiuqi.mobile.nigo.comeclose.json.JSONObject;
import com.jiuqi.mobile.nigo.comeclose.utils.DateUtils;
import com.jiuqi.mobile.nigo.comeclose.utils.StringUtils;
import com.jiuqi.mobile.nigo.comeclose.ws.WSConsts;
public class ClientInvocationHandler implements InvocationHandler {
/**
* 连接超时
*/
private static int TIMEOUT = 10 * 1000; // 10秒 static final
private String serverURL = null;
private String serviceURI = null;
private Class<?> intf = null;
private String sessionID;
private String account;
private String password;
private int time;
public void setAccount(String account) {
this.account = account;
}
public void setPassword(String password) {
this.password = password;
}
public Class<?> getIntf() {
return intf;
}
public void setIntf(Class<?> intf) {
this.intf = intf;
}
public String getSessionID() {
return sessionID;
}
public void setSessionID(String sessionID) {
this.sessionID = sessionID;
}
/**
* 构造函数
*
* @param serverURL
* 服务地址
* @param serviceURI
* 业务服务对相应的相对地址
* @param sessionID
*/
public ClientInvocationHandler(String serverURL, String serviceURI,
String sessionID, String account,String password,Class<?> intf) {
this(serverURL, serviceURI, sessionID,account,password, intf, 10 * 1000);
}
public ClientInvocationHandler(String serverURL, String serviceURI,
String sessionID,String account,String password, Class<?> intf, int timeout) {
this.serverURL = serverURL;
this.serviceURI = serviceURI;
this.sessionID = sessionID;
this.account = account;
this.password = password;
this.intf = intf;
this.TIMEOUT = timeout;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
String intfName = intf.getName();
String methodName = method.getName();
JSONArray params = params2JSON(args);
String serviceURL = getServiceURL();
HttpURLConnection conn = connect(serviceURL);
// JSONObject ret = doPost(conn, intfName, methodName, params);
Object obj = doPost(proxy,method,args,conn, intfName, methodName, params);
if (obj instanceof JSONObject) {
JSONObject ret = (JSONObject) obj;
Type returnType = method.getGenericReturnType();
// android 2.2
try {
if (null != returnType && null != returnType.toString()
&& !(returnType.toString().contains("."))) {
return JSONConvertor2.unSerializable(ret);
}
} catch (Throwable e) {
}
return JSONConvertor2.unAutoSerializable(ret, returnType);
// // if(returnType.isArray()){
// // Wrapper w = JSONConvertor2.unSerializable(Wrapper.class, ret);
// // return w.getRet();
// // }
// Object retObj = JSONConvertor2.unSerializable(returnType, ret);
// return retObj;
} else {
return obj;
}
}
private String getServiceURL() {
String url = serverURL + serviceURI;
return url;
}
// 连接
private HttpURLConnection connect(String url) throws NiGoException {
URL _url = null;
try {
_url = new URL(url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) _url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setUseCaches(false);
conn.setRequestProperty("Content-type", WSConsts.HTTP_CONNTENT_TYPE);
conn.setRequestProperty("Charset", WSConsts.CHARSET);
conn.setConnectTimeout(TIMEOUT);
conn.connect();
} catch (IOException e) {
throw new ConnectServiceFailException(url);
}
return conn;
}
// 执行
private Object doPost(Object proxy,Method method, Object[] args,HttpURLConnection conn, String intfName,
String methodName, JSONArray params) throws Throwable {
PrintWriter out = new PrintWriter(new OutputStreamWriter(
conn.getOutputStream(), WSConsts.CHARSET));
String requestString = getRequestString(intfName, methodName, params);
out.print(requestString);
out.flush();
out.close();
StringBuilder sResult = new StringBuilder();
conn.setConnectTimeout(5000);
int responseCode = conn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
InputStream httpInput = null;
BufferedReader httpReader = null;
// 读取数据
httpInput = conn.getInputStream();
httpReader = new BufferedReader(new InputStreamReader(httpInput,
WSConsts.CHARSET));
String line = null;
while ((line = httpReader.readLine()) != null) {
if (sResult.length() > 0) {
sResult.append("\n");
}
sResult.append(line);
}
} else {
throw new WSFailException("请求服务器失败:" + responseCode + ";url:"
+ conn.getURL().toString());
}
JSONObject result = new JSONObject(sResult.toString());
boolean error = result.getBoolean(WSConsts.REQUEST_ERRORED);
if (error) {
String errorMsg = "";
if (result.has(WSConsts.RESPONSE_ERROR_MSG)) {
errorMsg = result.getString(WSConsts.RESPONSE_ERROR_MSG);
}
if (result.has(WSConsts.RESPONSE_ERROR_EXCEPTION_CLASS)) {
try {
String eClass = result
.getString(WSConsts.RESPONSE_ERROR_EXCEPTION_CLASS);
Class<?> ex = Class.forName(eClass, true, Thread
.currentThread().getContextClassLoader());
Constructor<? extends Throwable> con;
if ("".equals(errorMsg)) {
con = (Constructor<? extends Throwable>) ex
.getDeclaredConstructor();
if (null != con) {
throw con.newInstance();
}
} else {
con = (Constructor<? extends Throwable>) ex
.getDeclaredConstructor(String.class);
if (null != con) {
throw con.newInstance(errorMsg);
}
}
if (null == con) {
con = (Constructor<? extends Throwable>) ex
.getDeclaredConstructor(String.class,
Throwable.class);
if (null != con) {
throw con.newInstance(errorMsg, (Throwable) null);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
if (null == errorMsg || "".equals(errorMsg.trim())) {
throw new WSRequestErrorException("服务器未知异常");
} else{
/**
* Session超时时抛出异常errorMsg = 您的登录信息已过期,请重新登录!
*/
if(null!=errorMsg&&errorMsg.contains("登录信息已过期")){
if(time<2){
try {
if(!StringUtils.isEmpty(account, true)){
ClientContext aa = ClientContext.getClientContext(serverURL, account, password);
this.sessionID = aa.getSessionID();
time++;
return this.invoke(proxy, method, args);
}
} catch (Exception e) {
throw new WSRequestErrorException("自动登录失败");
}
}else{
time=0;
throw new WSRequestErrorException(errorMsg);
}
}else{
throw new WSRequestErrorException(errorMsg);
}
}
} else {
if (!result.has(WSConsts.RESPONSE_DATA)) {
return null;
}
try {
JSONObject resultData = result
.getJSONObject(WSConsts.RESPONSE_DATA);
return resultData;
} catch (JSONException e) {
Object obj = result.get(WSConsts.RESPONSE_DATA);
return obj;
}
}
return error;
}
// 将params转换成json格式的字符串
private JSONArray params2JSON(Object[] params) {
return JSONConvertor2.serializableArray(params);
}
// 得到请求的字符串
private String getRequestString(String intfName, String methodName,
JSONArray params) throws JSONException {
JSONObject requestJSON = getRequestData(intfName, methodName, params);
// String requestString = WSConsts.REQUEST_DATA + "=" +
// requestJSON.toString();
// return requestString;
return requestJSON.toString();
}
// 将请求参数转换成JSON对象
private JSONObject getRequestData(String intfName, String methodName,
JSONArray params) throws JSONException {
JSONObject ret = new JSONObject();
ret.put(WSConsts.REQUEST_TAG_INTF_NAME, intfName);
ret.put(WSConsts.REQUEST_TAG_METHOD_NAME, methodName);
ret.put(WSConsts.REQUEST_TAG_ARGS, params);
ret.put(WSConsts.REQUEST_SESSION, sessionID);
return ret;
}
}