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.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
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.JSONConvertor;
import com.jiuqi.mobile.nigo.comeclose.json.JSONException;
import com.jiuqi.mobile.nigo.comeclose.json.JSONObject;
import com.jiuqi.mobile.nigo.comeclose.ws.WSConsts;
import com.jiuqi.mobile.nigo.comeclose.ws.server.Wrapper;
/**
* webservice 代理执行核心,负责网络等相关任务
* @author liuhongbin
*/
public class WSInvocationHandler implements InvocationHandler {
/**
* 连接超时
*/
private static final int TIMEOUT = 10*1000; //10秒
private String serverURL = null;
private String serviceURI = null;
private Class<?> intf = null;
private String sessionID;
/**
* 构造函数
* @param serverURL 服务地址
* @param serviceURI 业务服务对相应的相对地址
* @param sessionID
*/
public WSInvocationHandler(String serverURL, String serviceURI, String sessionID, Class<?> intf) {
this.serverURL = serverURL;
this.serviceURI = serviceURI;
this.sessionID = sessionID;
this.intf = intf;
}
@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(conn, intfName, methodName, params);
if(obj instanceof JSONObject){
JSONObject ret = (JSONObject) obj;
Class<?> returnType = method.getReturnType();
if(returnType.isArray()){
Wrapper w = JSONConvertor.unSerializable(Wrapper.class, ret);
return w.getRet();
}
Object retObj = JSONConvertor.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(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();
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("请求服务器失败");
}
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) {
}
}
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;
}
}
}
// 将params转换成json格式的字符串
private JSONArray params2JSON(Object[] params) {
JSONArray ret = new JSONArray()/*(JSONObject) JSONConvertor.serializable(params)*/;
if (params == null || params.length <= 0) {
return ret;
}
for (int i = 0; i < params.length; i++) {
Object param = params[i];
// JSONObject json = (JSONObject) JSONConvertor.serializable(param);
Object json = JSONConvertor.serializable(param);
ret.put(json);
}
return ret;
}
// 得到请求的字符串
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;
}
}