@Override public Object invokeMethod(String name, Object param) { try { if (controller == null) { controller = Request.current().controller; } String action = controller + "." + name; if (action.endsWith(".call")) { action = action.substring(0, action.length() - 5); } try { Map<String, Object> r = new HashMap<String, Object>(); Method actionMethod = (Method) ActionInvoker.getActionMethod(action)[1]; String[] names = (String[]) actionMethod.getDeclaringClass().getDeclaredField("$" + actionMethod.getName() + LocalVariablesNamesTracer.computeMethodHash(actionMethod.getParameterTypes())).get(null); if (param instanceof Object[]) { // too many parameters versus action, possibly a developer error. we must warn him. if (names.length < ((Object[]) param).length) { throw new NoRouteFoundException(action, null); } for (int i = 0; i < ((Object[]) param).length; i++) { if (((Object[]) param)[i] instanceof Router.ActionDefinition && ((Object[]) param)[i] != null) { Unbinder.unBind(r, ((Object[]) param)[i].toString(), i < names.length ? names[i] : ""); } else if (isSimpleParam(actionMethod.getParameterTypes()[i])) { if (((Object[]) param)[i] != null) { Unbinder.unBind(r, ((Object[]) param)[i].toString(), i < names.length ? names[i] : ""); } } else { Unbinder.unBind(r, ((Object[]) param)[i], i < names.length ? names[i] : ""); } } } Router.ActionDefinition def = Router.reverse(action, r); if (absolute) { def.absolute(); } if (template.template.name.endsWith(".html") || template.template.name.endsWith(".xml")) { def.url = def.url.replace("&", "&"); } return def; } catch (ActionNotFoundException e) { throw new NoRouteFoundException(action, null); } } catch (Exception e) { if (e instanceof PlayException) { throw (PlayException) e; } throw new UnexpectedException(e); } }
/** * 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(); }