private void handleJsonResponses() { ServletRequestInfo info = getServletRequestInfo(); if (info.currentJsonRequest == null) return; info.response.setContentType("application/json"); info.response.setCharacterEncoding("UTF-8"); String result; try { if (info.jsonResponses.size() == 0) { ServletOutputStream out = info.getOutputStream(); out.close(); out.flush(); return; } if (!info.isBatchRequest) { result = (new Gson()).toJson(info.jsonResponses.get(0)); } else { result = (new Gson()).toJson(info.jsonResponses); } PrintWriter writer = new PrintWriter(info.getOutputStream()); writer.print(result); writer.close(); writer.flush(); } catch (Exception e) { e.printStackTrace(); } }
private void handleArrayOfJsonRequests( PeekableInputStream inputStream, HttpServletResponse response) throws IOException { try { JsonRpcRequestModel[] jsonRequests; String streamString = IOUtils.toString(inputStream, "UTF-8"); ServletRequestInfo info = getServletRequestInfo(); /*If first character is { then it is a single request. We add it to the array jsonRequests and continue*/ if (streamString.charAt(0) == '{') { // TODO:CHeck parse error for this JsonRpcRequestModel req = (new Gson()).fromJson(streamString, JsonRpcRequestModel.class); jsonRequests = new JsonRpcRequestModel[] {req}; info.isBatchRequest = false; } else { jsonRequests = (new Gson()).fromJson(streamString, JsonRpcRequestModel[].class); info.isBatchRequest = true; } /* we loop through each request, get results or check error and add repsonses to an array*/ for (int i = 0; i < jsonRequests.length; i++) { info.currentJsonRequest = jsonRequests[i]; /* Check to see if JSON-RPC protocol is 2.0*/ if (info.currentJsonRequest.jsonrpc == null || !info.currentJsonRequest.jsonrpc.equals(JSONRPC_VERSION)) { sendJsonError(JSON_RPC_PROTOCOL_ERROR_MESSAGE, info.currentJsonRequest.jsonrpc); continue; } /*Check if ID is a number and if so it has not fractional numbers*/ else if (info.currentJsonRequest.id instanceof Number) { Number number = (Number) info.currentJsonRequest.id; if (number.intValue() != number.doubleValue()) { sendJsonError(JSON_RPC_ID_ERROR_MESSAGE, info.currentJsonRequest.id); continue; } info.currentJsonRequest.id = number.intValue(); } /*Check if Method exists*/ if (!methodMap.containsKey(info.currentJsonRequest.method)) { sendJsonError(JSON_RPC_METHOD_ERROR_MESSAGE, info.currentJsonRequest.method); continue; } invokeMethod(info.currentJsonRequest.method, info.currentJsonRequest.params); } } catch (JsonParseException e) { sendError(e, JSON_RPC_PARSE_ERROR_MESSAGE); } }
@SuppressWarnings("unchecked") private void handleServletRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { try { ServletRequestInfo info = setServletRequestInfo(request, response); if (request.getMethod().equals("GET")) { List<String> urlParamNames = Collections.list(request.getParameterNames()); HashMap<String, String> params = new HashMap<String, String>(); for (String paramName : urlParamNames) params.put(paramName, request.getParameter(paramName)); JsonRpcRequestModel json = new JsonRpcRequestModel(); json.jsonrpc = JSONRPC_VERSION; json.id = ""; json.method = params.remove(METHOD); json.params = params; info.currentJsonRequest = json; invokeMethod(json.method, params); } else // post { try { String methodName; Object methodParams; if (info.inputStream.peek() == '[' || info.inputStream.peek() == '{') // json { handleArrayOfJsonRequests(info.inputStream, response); } else // AMF3 { ASObject obj = (ASObject) deserializeAmf3(info.inputStream); methodName = (String) obj.get(METHOD); methodParams = obj.get(PARAMS); info.streamParameterIndex = (Number) obj.get(STREAM_PARAMETER_INDEX); invokeMethod(methodName, methodParams); } } catch (IOException e) { sendError(e, null); } catch (Exception e) { sendError(e, null); } } handleJsonResponses(); } finally { removeServletRequestInfo(); } }
private void sendError(Throwable exception, String moreInfo) throws IOException { if (exception instanceof InvocationTargetException) exception = exception.getCause(); // log errors exception.printStackTrace(); String message; if (exception instanceof RuntimeException) message = exception.toString(); else message = exception.getMessage(); if (moreInfo != null) message += "\n" + moreInfo; System.err.println("Serializing ErrorMessage: " + message); ServletRequestInfo info = getServletRequestInfo(); if (info.currentJsonRequest == null) { ServletOutputStream servletOutputStream = info.getOutputStream(); ErrorMessage errorMessage = new ErrorMessage(new MessageException(message)); errorMessage.faultCode = exception.getClass().getSimpleName(); serializeCompressedAmf3(errorMessage, servletOutputStream); } else { sendJsonError(message, null); } }
/** * @param methodName The name of the function to invoke. * @param methodParams A Map, List, or Array of input parameters for the method. Values will be * cast to the appropriate types if necessary. */ private void invokeMethod(String methodName, Object methodParams) throws IOException { ServletRequestInfo info = getServletRequestInfo(); if (!methodMap.containsKey(methodName) || methodMap.get(methodName) == null) { sendError( new IllegalArgumentException(String.format("Method \"%s\" not supported.", methodName)), null); return; } if (methodParams == null) methodParams = new Object[0]; if (methodParams instanceof Map) methodParams = getParamsFromMap(methodName, (Map<?, ?>) methodParams); if (methodParams instanceof List<?>) methodParams = ((List<?>) methodParams).toArray(); if (info.streamParameterIndex != null) { int index = info.streamParameterIndex.intValue(); if (index >= 0) ((Object[]) methodParams)[index] = info.inputStream; } Object[] params = (Object[]) methodParams; // get method by name ExposedMethod exposedMethod = methodMap.get(methodName); if (exposedMethod == null) { sendError(new IllegalArgumentException("Unknown method: " + methodName), null); return; } // cast input values to appropriate types if necessary Class<?>[] expectedArgTypes = exposedMethod.method.getParameterTypes(); if (expectedArgTypes.length == params.length) { for (int index = 0; index < params.length; index++) { params[index] = cast(params[index], expectedArgTypes[index]); } } // prepare to output the result of the method call long startTime = System.currentTimeMillis(); // Invoke the method on the object with the arguments try { Object result = exposedMethod.method.invoke(exposedMethod.instance, params); if (info.currentJsonRequest == null) // AMF3 { if (exposedMethod.method.getReturnType() != void.class) { ServletOutputStream servletOutputStream = info.getOutputStream(); serializeCompressedAmf3(result, servletOutputStream); } } else // json { Object id = info.currentJsonRequest.id; /* If ID is empty then it is a notification, we send nothing back */ if (id != null) { JsonRpcResponseModel responseObj = new JsonRpcResponseModel(); responseObj.jsonrpc = "2.0"; responseObj.result = result; responseObj.id = id; info.jsonResponses.add(responseObj); } } } catch (InvocationTargetException e) { System.err.println(methodToString(methodName, params)); sendError(e, null); } catch (IllegalArgumentException e) { String moreInfo = "Expected: " + formatFunctionSignature(methodName, expectedArgTypes, exposedMethod.paramNames) + "\n" + "Received: " + formatFunctionSignature(methodName, params, null); sendError(e, moreInfo); } catch (Exception e) { System.err.println(methodToString(methodName, params)); sendError(e, null); } long endTime = System.currentTimeMillis(); // debug if (endTime - startTime >= debugThreshold) System.out.println( String.format("[%sms] %s", endTime - startTime, methodToString(methodName, params))); }