@Override public Object resolve( MethodAction action, RouteType routeType, HttpServletRequest req, HttpServletResponse resp, Map<String, String> pathVars) throws ActionException { Object controller = getOrCreateController(action); Map<Annotation, ActionInterceptor<Annotation>> interceptors = action.interceptors(); Object result = null; Exception exception = null; try { result = beforeInterceptors(interceptors, req, resp); List<?> arguments = bindArguments(action, req, resp, pathVars); result = result != null ? result : action.invoke(controller, arguments); result = afterInterceptors(result, interceptors, req, resp); } catch (InvocationTargetException e) { // we need to unwrap InvocationTargetExceptions to get at the real exception exception = Cast.as(e.getTargetException(), Exception.class); if (exception == null) { throw new BaseException(e); } } catch (Exception e) { exception = e; } if (exception != null) { result = exceptionInterceptors(interceptors, req, resp, exception); if (result == null) { throw new ActionException(exception, "Failed in %s: %s", action, exception.getMessage()); } } Logger.debug("%s -> %s resolved", req.getRequestURI(), action); return result; }
@Override public MethodAction createActionIfPossible(String actionName) { // will resolve if both a class and method name can be parsed, and a valid class with that // method name can be loaded String methodName = MethodAction.methodNameForAction(actionName); String className = MethodAction.classNameForAction(actionName); if (StringUtils.isEmpty(methodName) || StringUtils.isEmpty(className)) { return null; } try { Class<?> clazz = Class.forName(className); // TODO - Restricted in GAE - why is this better? // ClassLoaderUtil.loadClass(className); Method method = ReflectUtil.findMethod(clazz, methodName); if (method == null) { return null; } MethodAction methodAction = new MethodAction(clazz, method, findInterceptors(method)); // force instantiation of controller - this allows controllers to be injected into eachother // and also flushes out instantiation issues at startup Object controller = createController(methodAction); controllerInstances.put(methodAction.type(), controller); return methodAction; } catch (BaseException e) { throw e; } catch (Exception e) { return null; } }
/** * Creates the power on action. * * @return the method action */ MethodAction createPowerOnAction() { MethodAction action = new MethodAction(); action.setName("PowerOnVM_Task"); MethodActionArgument argument = new MethodActionArgument(); argument.setValue(null); action.getArgument().addAll(Arrays.asList(new MethodActionArgument[] {argument})); return action; }
private Object getOrCreateController(MethodAction methodAction) { Object controller = controllerInstances.get(methodAction.type()); if (controller == null) { synchronized (controllerInstances) { controller = controllerInstances.get(methodAction.type()); if (controller == null) { controller = createController(methodAction); controllerInstances.put(methodAction.type(), controller); } } } return controller; }
<T> T createController(MethodAction actionMethod) { Class<T> type = actionMethod.type(); if (!injectionContext.contains(type)) { injectionContext.inject(type).as(type); } try { return injectionContext.get(type); } catch (Exception e) { throw new ActionException( e, "Failed to create controller %s: %s", type.toString(), e.getMessage()); } }
List<Object> bindArguments( MethodAction action, HttpServletRequest req, HttpServletResponse resp, Map<String, String> pathVars) { Map<ParameterDescription, Object> boundParameters = new LinkedHashMap<ParameterDescription, Object>(); for (ParameterDescription parameterDescription : action.parameters()) { boundParameters.put(parameterDescription, null); } if (!boundParameters.isEmpty()) { for (ActionMethodBinder binder : methodBinderRegistry.getRegisteredActionMethodBinders()) { binder.bindAll(boundParameters, req, resp, pathVars); } } return new ArrayList<Object>(boundParameters.values()); }