final Object requestId,
final JSONSerializerController serializer,
final CallbackController cbc,
final IExceptionTransformer exceptionTransformer) {
final Logger logger = getLogger();
JSONRPCResult result;
// Call the method
try {
final boolean isConstructor = accessibleObject instanceof Constructor;
if (logger.isLoggable(Level.FINE)) {
if (!isConstructor) {
logger.log(Level.FINE, "invoking {0} {1}({2})",
new Object[]{
((Method) accessibleObject).getReturnType().getName(),
((Method) accessibleObject).getName(),
argSignature(accessibleObject)});
} else {
logger.log(Level.FINE, "invoking {0}" + " " + "(" + "{1})",
new Object[]{
((Constructor) accessibleObject).getName(),
argSignature(accessibleObject)});
}
}
final Class[] parameterTypes;
if (isConstructor) {
parameterTypes = ((Constructor) accessibleObject).getParameterTypes();
} else {
parameterTypes = ((Method) accessibleObject).getParameterTypes();
}
// Unmarshall arguments
final Object javaArgs[] = this.unmarshallArgs(context,
parameterTypes, arguments, serializer);
// Call pre invoke callbacks
if (cbc != null) {
for (int i = 0; i < context.length; i++) {
cbc.preInvokeCallback(context[i], javascriptObject, accessibleObject,
javaArgs);
}
}
// Invoke the method
final Object returnObj;
if (isConstructor) {
returnObj = ((Constructor) accessibleObject).newInstance(javaArgs);
} else {
returnObj = ((Method) accessibleObject).invoke(javascriptObject,
javaArgs);
}
// Call post invoke callbacks
if (cbc != null) {
for (int i = 0; i < context.length; i++) {
cbc.postInvokeCallback(context[i], javascriptObject,
accessibleObject, returnObj);
}
}
// Marshall the result
final SerializerState serializerState = new SerializerState();
final Object json = serializer.marshall(serializerState, null, returnObj, "r");
result = new JSONRPCResult(JSONRPCResult.CODE_SUCCESS,
requestId,
json,
serializerState.getFixUps());
// Handle exceptions creating exception results and
// calling error callbacks
} catch (UnmarshallException e) {
if (cbc != null) {
for (int i = 0; i < context.length; i++) {
cbc.errorCallback(context[i], javascriptObject, accessibleObject, e);
}
}
result = new JSONRPCResult(JSONRPCResult.CODE_ERR_UNMARSHALL, requestId,
e.getMessage());
} catch (MarshallException e) {
if (cbc != null) {
for (int i = 0; i < context.length; i++) {
cbc.errorCallback(context[i], javascriptObject, accessibleObject, e);
}
}
result = new JSONRPCResult(JSONRPCResult.CODE_ERR_MARSHALL, requestId, e.getMessage());
} catch (Throwable e) {
if (e instanceof InvocationTargetException) {
e = ((InvocationTargetException) e).getTargetException();
}
// handle Jetty continuations-- this is kind of a hack
// but at least this will work without requiring jetty as
// a dependent library
if ("org.mortbay.jetty.RetryRequest".equals(e.getClass().getName())) {
throw (RuntimeException) e;
}
if (cbc != null) {
for (int i = 0; i < context.length; i++) {
cbc.errorCallback(context[i], javascriptObject, accessibleObject, e);
}
}
result = new JSONRPCResult(JSONRPCResult.CODE_REMOTE_EXCEPTION,
requestId, exceptionTransformer.transform(e));
}
return result;
}