Search in sources :

Example 1 with RPCResponse

use of org.apache.struts2.json.rpc.RPCResponse in project struts by apache.

the class JSONInterceptor method invoke.

@SuppressWarnings("unchecked")
public RPCResponse invoke(Object object, Map data) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, JSONException, InstantiationException, NoSuchMethodException, IntrospectionException {
    RPCResponse response = new RPCResponse();
    // validate id
    Object id = data.get("id");
    if (id == null) {
        String message = "'id' is required for JSON RPC";
        response.setError(new RPCError(message, RPCErrorCode.METHOD_NOT_FOUND));
        return response;
    }
    // could be a numeric value
    response.setId(id.toString());
    // the map is going to have: 'params', 'method' and 'id' (for the
    // client to identify the response)
    Class clazz = object.getClass();
    // parameters
    List parameters = (List) data.get("params");
    int parameterCount = parameters != null ? parameters.size() : 0;
    // method
    String methodName = (String) data.get("method");
    if (methodName == null) {
        String message = "'method' is required for JSON RPC";
        response.setError(new RPCError(message, RPCErrorCode.MISSING_METHOD));
        return response;
    }
    Method method = this.getMethod(clazz, methodName, parameterCount);
    if (method == null) {
        String message = "Method " + methodName + " could not be found in action class.";
        response.setError(new RPCError(message, RPCErrorCode.METHOD_NOT_FOUND));
        return response;
    }
    // parameters
    if (parameterCount > 0) {
        Class[] parameterTypes = method.getParameterTypes();
        Type[] genericTypes = method.getGenericParameterTypes();
        List invocationParameters = new ArrayList();
        // validate size
        if (parameterTypes.length != parameterCount) {
            // size mismatch
            String message = "Parameter count in request, " + parameterCount + " do not match expected parameter count for " + methodName + ", " + parameterTypes.length;
            response.setError(new RPCError(message, RPCErrorCode.PARAMETERS_MISMATCH));
            return response;
        }
        // convert parameters
        for (int i = 0; i < parameters.size(); i++) {
            Object parameter = parameters.get(i);
            Class paramType = parameterTypes[i];
            Type genericType = genericTypes[i];
            // clean up the values
            if (dataCleaner != null) {
                parameter = dataCleaner.clean("[" + i + "]", parameter);
            }
            Object converted = populator.convert(paramType, genericType, parameter, method);
            invocationParameters.add(converted);
        }
        response.setResult(method.invoke(object, invocationParameters.toArray()));
    } else {
        response.setResult(method.invoke(object, new Object[0]));
    }
    return response;
}
Also used : Type(java.lang.reflect.Type) RPCResponse(org.apache.struts2.json.rpc.RPCResponse) RPCError(org.apache.struts2.json.rpc.RPCError) SMDMethod(org.apache.struts2.json.annotations.SMDMethod) Method(java.lang.reflect.Method)

Example 2 with RPCResponse

use of org.apache.struts2.json.rpc.RPCResponse in project struts by apache.

the class JSONInterceptor method intercept.

@SuppressWarnings("unchecked")
public String intercept(ActionInvocation invocation) throws Exception {
    HttpServletRequest request = ServletActionContext.getRequest();
    HttpServletResponse response = ServletActionContext.getResponse();
    String requestContentType = readContentType(request);
    String requestContentTypeEncoding = readContentTypeEncoding(request);
    Object rootObject = null;
    final ValueStack stack = invocation.getStack();
    if (this.root != null) {
        rootObject = stack.findValue(this.root);
        if (rootObject == null) {
            throw new RuntimeException("Invalid root expression: '" + this.root + "'.");
        }
    }
    if (jsonContentType.equalsIgnoreCase(requestContentType)) {
        // load JSON object
        Object obj = JSONUtil.deserialize(request.getReader());
        // JSON array (this.root cannot be null in this case)
        if (obj instanceof List && this.root != null) {
            String mapKey = this.root;
            rootObject = null;
            if (this.root.indexOf('.') != -1) {
                mapKey = this.root.substring(this.root.lastIndexOf('.') + 1);
                rootObject = stack.findValue(this.root.substring(0, this.root.lastIndexOf('.')));
                if (rootObject == null) {
                    throw new RuntimeException("JSON array: Invalid root expression: '" + this.root + "'.");
                }
            }
            // create a map with a list inside
            Map m = new HashMap();
            m.put(mapKey, new ArrayList((List) obj));
            obj = m;
        }
        if (obj instanceof Map) {
            Map json = (Map) obj;
            // clean up the values
            if (dataCleaner != null)
                dataCleaner.clean("", json);
            if (// model overrides action
            rootObject == null)
                rootObject = invocation.getStack().peek();
            // populate fields
            populator.populateObject(rootObject, json);
        } else {
            LOG.error("Unable to deserialize JSON object from request");
            throw new JSONException("Unable to deserialize JSON object from request");
        }
    } else if (jsonRpcContentType.equalsIgnoreCase(requestContentType)) {
        Object result;
        if (this.enableSMD) {
            // load JSON object
            Object obj = JSONUtil.deserialize(request.getReader());
            if (obj instanceof Map) {
                Map smd = (Map) obj;
                if (rootObject == null) {
                    // model makes no sense when using RPC
                    rootObject = invocation.getAction();
                }
                // invoke method
                try {
                    result = this.invoke(rootObject, smd);
                } catch (Exception e) {
                    RPCResponse rpcResponse = new RPCResponse();
                    rpcResponse.setId(smd.get("id").toString());
                    rpcResponse.setError(new RPCError(e, RPCErrorCode.EXCEPTION, getDebug()));
                    result = rpcResponse;
                }
            } else {
                String message = "SMD request was not in the right format. See http://json-rpc.org";
                RPCResponse rpcResponse = new RPCResponse();
                rpcResponse.setError(new RPCError(message, RPCErrorCode.INVALID_PROCEDURE_CALL));
                result = rpcResponse;
            }
        } else {
            String message = "Request with content type of 'application/json-rpc' was received but SMD is " + "not enabled for this interceptor. Set 'enableSMD' to true to enable it";
            RPCResponse rpcResponse = new RPCResponse();
            rpcResponse.setError(new RPCError(message, RPCErrorCode.SMD_DISABLED));
            result = rpcResponse;
        }
        JSONUtil jsonUtil = invocation.getInvocationContext().getContainer().getInstance(JSONUtil.class);
        String json = jsonUtil.serialize(result, excludeProperties, getIncludeProperties(), ignoreHierarchy, excludeNullProperties);
        json = addCallbackIfApplicable(request, json);
        boolean writeGzip = enableGZIP && JSONUtil.isGzipInRequest(request);
        JSONUtil.writeJSONToResponse(new SerializationParams(response, requestContentTypeEncoding, this.wrapWithComments, json, true, writeGzip, noCache, -1, -1, prefix, "application/json"));
        return Action.NONE;
    } else {
        LOG.debug("Accept header parameter must be '{}' or '{}'. Ignoring request with Content Type '{}'", jsonContentType, jsonRpcContentType, requestContentType);
    }
    return invocation.invoke();
}
Also used : ValueStack(com.opensymphony.xwork2.util.ValueStack) HttpServletResponse(javax.servlet.http.HttpServletResponse) RPCResponse(org.apache.struts2.json.rpc.RPCResponse) RPCError(org.apache.struts2.json.rpc.RPCError) IntrospectionException(java.beans.IntrospectionException) InvocationTargetException(java.lang.reflect.InvocationTargetException) HttpServletRequest(javax.servlet.http.HttpServletRequest)

Aggregations

RPCError (org.apache.struts2.json.rpc.RPCError)2 RPCResponse (org.apache.struts2.json.rpc.RPCResponse)2 ValueStack (com.opensymphony.xwork2.util.ValueStack)1 IntrospectionException (java.beans.IntrospectionException)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 Method (java.lang.reflect.Method)1 Type (java.lang.reflect.Type)1 HttpServletRequest (javax.servlet.http.HttpServletRequest)1 HttpServletResponse (javax.servlet.http.HttpServletResponse)1 SMDMethod (org.apache.struts2.json.annotations.SMDMethod)1