/*******************************************************************************
* Copyright © 2011, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*
*******************************************************************************/
package org.eclipse.edt.javart.services.servlet;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.edt.javart.Runtime;
import org.eclipse.edt.javart.json.ArrayNode;
import org.eclipse.edt.javart.json.JsonParser;
import org.eclipse.edt.javart.json.JsonUtilities;
import org.eclipse.edt.javart.json.ObjectNode;
import org.eclipse.edt.javart.messages.Message;
import org.eclipse.edt.javart.services.FunctionParameterKind;
import org.eclipse.edt.javart.services.FunctionSignature;
import org.eclipse.edt.javart.services.ServiceBase;
import org.eclipse.edt.javart.services.ServiceUtilities;
import org.eclipse.edt.runtime.java.eglx.lang.EDictionary;
import eglx.http.HttpUtilities;
import eglx.http.Request;
import eglx.http.Response;
import eglx.json.JsonLib;
import eglx.lang.AnyException;
import eglx.services.ServiceInvocationException;
import eglx.services.ServiceKind;
public class JsonRpcInvoker extends LocalServiceInvoker {
private static String JSON_RPC_METHOD_ID = "method";
private static String JSON_RPC_PARAMETER_ID = "params";
private static String JSON_RPC_RESULT_ID = "result";
public JsonRpcInvoker(String serviceClassName, ServiceKind serviceKind) {
super(serviceClassName, serviceKind);
}
public Response invoke(Request request)throws AnyException
{
if (trace()){
tracer().put("invoking " + getServiceClassName() + " using " + ServiceUtilities.convert(getServiceKind()));
}
Response response = new Response();
traceElapsedTime( true );
try{
ObjectNode jsonRequest = request.body == null ? new ObjectNode() : JsonParser.parse(request.body);
if (trace()){
tracer().put( " invoking function " + JsonUtilities.getValueNode(jsonRequest, JSON_RPC_METHOD_ID).toJava() );
}
String result = wrapperProxyReturn( invokeEglService(jsonRequest) );
traceElapsedTime( false );
if (trace()){
tracer().put( "return data from dedicated service:" + result == null ? "null" : result );
}
response.body = result;
boolean failed = resultContainsError( result );
response.status = failed ? HttpUtilities.HTTP_STATUS_FAILED: HttpUtilities.HTTP_STATUS_OK;
response.statusMessage = failed ? HttpUtilities.HTTP_STATUS_MSG_FAILED : HttpUtilities.HTTP_STATUS_MSG_OK;
}
catch(ServiceInvocationException sie){
response.body = eglx.json.JsonUtilities.createJsonAnyException(sie);
response.status = HttpUtilities.HTTP_STATUS_FAILED;
response.statusMessage = HttpUtilities.HTTP_STATUS_MSG_FAILED;
} catch (Throwable t) {
response.body = eglx.json.JsonUtilities.createJsonAnyException(
ServiceUtilities.buildServiceInvocationException(Message.SOA_E_EGL_SERVICE_INVOCATION, new String[]{request.body == null ? "null" : request.body, getServiceClassName()}, t, getServiceKind()));
response.status = HttpUtilities.HTTP_STATUS_FAILED;
response.statusMessage = HttpUtilities.HTTP_STATUS_MSG_FAILED;
}
return response;
}
public String invokeEglService( final ObjectNode jsonRequest ) throws ServiceInvocationException
{
String returnVal = null;
String methodName = JsonUtilities.getValueNode(jsonRequest, JSON_RPC_METHOD_ID).toJava();
try
{
Method method = getMethod(methodName);
Object[] parameters = eglx.json.JsonUtilities.getParameters(method, (ArrayNode)JsonUtilities.getValueNode(jsonRequest, JSON_RPC_PARAMETER_ID));
ServiceBase service = getService();
Runtime.getRunUnit().setActiveExecutable(service);
Object ret = method.invoke(service, parameters);
returnVal = convertToJson(method, parameters, ret);
Runtime.getRunUnit().endRunUnit(service);
}
catch (ServiceInvocationException sie)
{
throw sie;
}
catch (Throwable t)
{
throw ServiceUtilities.buildServiceInvocationException(Message.SOA_E_WS_SERVICE, new String[] {getServiceClassName(), methodName}, t, getServiceKind() );
}
return returnVal;
}
private String convertToJson(Method method, Object[] parameters, Object ret){
FunctionSignature signature = method.getAnnotation(FunctionSignature.class);
final List<Object> responseParameters = new ArrayList<Object>();
for(int idx = 0; idx < method.getParameterTypes().length; idx++){
if(!FunctionParameterKind.IN.equals(signature.parameters()[idx].kind())){
responseParameters.add(eglx.json.JsonUtilities.wrapCalendar(parameters[idx], signature.parameters()[idx].jsonInfo().clazz(), signature.parameters()[idx].jsonInfo().asOptions()));
}
}
if(ret != null){
responseParameters.add(eglx.json.JsonUtilities.wrapCalendar(ret, signature.parameters()[signature.parameters().length - 1].jsonInfo().clazz(), signature.parameters()[signature.parameters().length - 1].jsonInfo().asOptions()));
}
Object response;
if(responseParameters.size() == 0){
response = null;
}
else if(responseParameters.size() == 1){
response = responseParameters.get(0);
}
else{
response = responseParameters;
}
EDictionary responseObject = new EDictionary();
responseObject.put(JSON_RPC_RESULT_ID, response);
return JsonLib.convertToJSON(responseObject);
}
private String wrapperProxyReturn( Object returnVal )
{
return returnVal == null ? "{}" : returnVal.toString();
}
protected boolean resultContainsError( String result )
{
return result.indexOf( "{\"error\" : {" ) != -1;
}
@Override
public ServiceKind getServiceKind(Request innerRequest) {
return getServiceKind();
}
}