@Override public void beforeActionInvocation(Method actionMethod) { try { Validation.current.set(restore()); boolean verify = false; for (Annotation[] annotations : actionMethod.getParameterAnnotations()) { if (annotations.length > 0) { verify = true; break; } } if (!verify) { return; } List<ConstraintViolation> violations = new Validator().validateAction(actionMethod); ArrayList<Error> errors = new ArrayList<Error>(); String[] paramNames = Java.parameterNames(actionMethod); for (ConstraintViolation violation : violations) { errors.add( new Error( paramNames[((MethodParameterContext) violation.getContext()).getParameterIndex()], violation.getMessage(), violation.getMessageVariables() == null ? new String[0] : violation.getMessageVariables().values().toArray(new String[0]))); } Validation.current.get().errors.addAll(errors); } catch (Exception e) { throw new UnexpectedException(e); } }
public static Object[] getActionMethodArgs(Method method, Object o) throws Exception { String[] paramsNames = Java.parameterNames(method); if (paramsNames == null && method.getParameterTypes().length > 0) { throw new UnexpectedException("Parameter names not found for method " + method); } // Check if we have already performed the bind operation Object[] rArgs = CachedBoundActionMethodArgs.current().retrieveActionMethodArgs(method); if (rArgs != null) { // We have already performed the binding-operation for this method // in this request. return rArgs; } rArgs = new Object[method.getParameterTypes().length]; for (int i = 0; i < method.getParameterTypes().length; i++) { Class<?> type = method.getParameterTypes()[i]; Map<String, String[]> params = new HashMap<String, String[]>(); // In case of simple params, we don't want to parse the body. if (type.equals(String.class) || Number.class.isAssignableFrom(type) || type.isPrimitive()) { params.put(paramsNames[i], Scope.Params.current().getAll(paramsNames[i])); } else { params.putAll(Scope.Params.current().all()); } Logger.trace( "getActionMethodArgs name [" + paramsNames[i] + "] annotation [" + Utils.join(method.getParameterAnnotations()[i], " ") + "]"); RootParamNode root = ParamNode.convert(params); rArgs[i] = Binder.bind( root, paramsNames[i], method.getParameterTypes()[i], method.getGenericParameterTypes()[i], method.getParameterAnnotations()[i], new Binder.MethodAndParamInfo(o, method, i + 1)); } CachedBoundActionMethodArgs.current().storeActionMethodArgs(method, rArgs); return rArgs; }
/** * Parses the playframework action expressions. The string inside "()" is evaluated by OGNL in the * current context. * * @param arguments * @param attributeValue e.g. "Application.show(obj.id)" * @return parsed action path */ @SuppressWarnings("unchecked") static String toActionString(final Arguments arguments, String attributeValue) { Matcher matcher = PARAM_PATTERN.matcher(attributeValue); if (!matcher.matches()) { return Router.reverse(attributeValue).toString(); } String exp = matcher.group(1); if (StringUtils.isBlank(exp)) { return Router.reverse(attributeValue).toString(); } Object obj = PlayOgnlVariableExpressionEvaluator.INSTANCE.evaluate( arguments.getConfiguration(), arguments, exp, false); if (obj instanceof Map) { return Router.reverse(attributeValue, (Map<String, Object>) obj).toString(); } List<?> list = obj instanceof List ? (List<?>) obj : Arrays.asList(obj); Map<String, Object> paramMap = new HashMap<String, Object>(); String extracted = StringUtils.substringBefore(attributeValue, "("); if (!extracted.contains(".")) { extracted = Request.current().controller + "." + extracted; } Object[] actionMethods = ActionInvoker.getActionMethod(extracted); String[] paramNames = null; try { paramNames = Java.parameterNames((Method) actionMethods[1]); } catch (Exception e) { throw new RuntimeException(e); } if (paramNames.length < list.size()) { Logger.warn("param length unmatched. %s", Arrays.toString(paramNames)); throw new ActionNotFoundException(attributeValue, null); } for (int i = 0; i < list.size(); i++) { paramMap.put(paramNames[i], list.get(i)); } return Router.reverse(extracted, paramMap).toString(); }