private static void handleAfters(Http.Request request) throws Exception { List<Method> afters = Java.findAllAnnotatedMethods(Controller.getControllerClass(), After.class); ControllerInstrumentation.stopActionCall(); for (Method after : afters) { String[] unless = after.getAnnotation(After.class).unless(); String[] only = after.getAnnotation(After.class).only(); boolean skip = false; for (String un : only) { if (!un.contains(".")) { un = after.getDeclaringClass().getName().substring(12) + "." + un; } if (un.equals(request.action)) { skip = false; break; } else { skip = true; } } for (String un : unless) { if (!un.contains(".")) { un = after.getDeclaringClass().getName().substring(12) + "." + un; } if (un.equals(request.action)) { skip = true; break; } } if (!skip) { after.setAccessible(true); inferResult(invokeControllerMethod(after)); } } }
private static void handleBefores(Http.Request request) throws Exception { List<Method> befores = Java.findAllAnnotatedMethods(Controller.getControllerClass(), Before.class); Collections.sort( befores, new Comparator<Method>() { public int compare(Method m1, Method m2) { Before before1 = m1.getAnnotation(Before.class); Before before2 = m2.getAnnotation(Before.class); return before1.priority() - before2.priority(); } }); ControllerInstrumentation.stopActionCall(); for (Method before : befores) { String[] unless = before.getAnnotation(Before.class).unless(); String[] only = before.getAnnotation(Before.class).only(); boolean skip = false; for (String un : only) { if (!un.contains(".")) { un = before.getDeclaringClass().getName().substring(12).replace("$", "") + "." + un; } if (un.equals(request.action)) { skip = false; break; } else { skip = true; } } for (String un : unless) { if (!un.contains(".")) { un = before.getDeclaringClass().getName().substring(12).replace("$", "") + "." + un; } if (un.equals(request.action)) { skip = true; break; } } if (!skip) { before.setAccessible(true); inferResult(invokeControllerMethod(before)); } } }
/** * Checks and calla all methods in controller annotated with @Finally. The caughtException-value * is sent as argument to @Finally-method if method has one argument which is Throwable * * @param request * @param caughtException If @Finally-methods are called after an error, this variable holds the * caught error * @throws PlayException */ static void handleFinallies(Http.Request request, Throwable caughtException) throws PlayException { if (Controller.getControllerClass() == null) { // skip it return; } try { List<Method> allFinally = Java.findAllAnnotatedMethods(Controller.getControllerClass(), Finally.class); ControllerInstrumentation.stopActionCall(); for (Method aFinally : allFinally) { String[] unless = aFinally.getAnnotation(Finally.class).unless(); String[] only = aFinally.getAnnotation(Finally.class).only(); boolean skip = false; for (String un : only) { if (!un.contains(".")) { un = aFinally.getDeclaringClass().getName().substring(12) + "." + un; } if (un.equals(request.action)) { skip = false; break; } else { skip = true; } } for (String un : unless) { if (!un.contains(".")) { un = aFinally.getDeclaringClass().getName().substring(12) + "." + un; } if (un.equals(request.action)) { skip = true; break; } } if (!skip) { aFinally.setAccessible(true); // check if method accepts Throwable as only parameter Class[] parameterTypes = aFinally.getParameterTypes(); if (parameterTypes.length == 1 && parameterTypes[0] == Throwable.class) { // invoking @Finally method with caughtException as // parameter invokeControllerMethod(aFinally, new Object[] {caughtException}); } else { // invoce @Finally-method the regular way without // caughtException invokeControllerMethod(aFinally, null); } } } } catch (InvocationTargetException ex) { StackTraceElement element = PlayException.getInterestingStackTraceElement(ex.getTargetException()); if (element != null) { throw new JavaExecutionException( Play.classes.getApplicationClass(element.getClassName()), element.getLineNumber(), ex.getTargetException()); } throw new JavaExecutionException(Http.Request.current().action, ex); } catch (Exception e) { throw new UnexpectedException("Exception while doing @Finally", e); } }
public static void invoke(Http.Request request, Http.Response response) { Monitor monitor = null; try { resolve(request, response); Method actionMethod = request.invokedMethod; // 1. Prepare request params Scope.Params.current().__mergeWith(request.routeArgs); // add parameters from the URI query string String encoding = Http.Request.current().encoding; Scope.Params.current() ._mergeWith( UrlEncodedParser.parseQueryString( new ByteArrayInputStream(request.querystring.getBytes(encoding)))); // 2. Easy debugging ... if (Play.mode == Play.Mode.DEV) { Class<Controller> cclass = Controller.class; cclass.getDeclaredField("params").set(null, Scope.Params.current()); cclass.getDeclaredField("request").set(null, Http.Request.current()); cclass.getDeclaredField("response").set(null, Http.Response.current()); cclass.getDeclaredField("session").set(null, Scope.Session.current()); cclass.getDeclaredField("flash").set(null, Scope.Flash.current()); cclass.getDeclaredField("renderArgs").set(null, Scope.RenderArgs.current()); cclass.getDeclaredField("routeArgs").set(null, Scope.RouteArgs.current()); cclass.getDeclaredField("validation").set(null, Validation.current()); } ControllerInstrumentation.stopActionCall(); Play.pluginCollection.beforeActionInvocation(actionMethod); // Monitoring monitor = MonitorFactory.start(request.action + "()"); // 3. Invoke the action try { // @Before handleBefores(request); // Action Result actionResult = null; String cacheKey = null; // Check the cache (only for GET or HEAD) if ((request.method.equals("GET") || request.method.equals("HEAD")) && actionMethod.isAnnotationPresent(CacheFor.class)) { cacheKey = actionMethod.getAnnotation(CacheFor.class).id(); if ("".equals(cacheKey)) { cacheKey = "urlcache:" + request.url + request.querystring; } actionResult = (Result) play.cache.Cache.get(cacheKey); } if (actionResult == null) { ControllerInstrumentation.initActionCall(); try { inferResult(invokeControllerMethod(actionMethod)); } catch (Result result) { actionResult = result; // Cache it if needed if (cacheKey != null) { play.cache.Cache.set( cacheKey, actionResult, actionMethod.getAnnotation(CacheFor.class).value()); } } catch (InvocationTargetException ex) { // It's a Result ? (expected) if (ex.getTargetException() instanceof Result) { actionResult = (Result) ex.getTargetException(); // Cache it if needed if (cacheKey != null) { play.cache.Cache.set( cacheKey, actionResult, actionMethod.getAnnotation(CacheFor.class).value()); } } else { // @Catch Object[] args = new Object[] {ex.getTargetException()}; List<Method> catches = Java.findAllAnnotatedMethods(Controller.getControllerClass(), Catch.class); ControllerInstrumentation.stopActionCall(); for (Method mCatch : catches) { Class[] exceptions = mCatch.getAnnotation(Catch.class).value(); if (exceptions.length == 0) { exceptions = new Class[] {Exception.class}; } for (Class exception : exceptions) { if (exception.isInstance(args[0])) { mCatch.setAccessible(true); inferResult(invokeControllerMethod(mCatch, args)); break; } } } throw ex; } } } // @After handleAfters(request); monitor.stop(); monitor = null; // OK, re-throw the original action result if (actionResult != null) { throw actionResult; } throw new NoResult(); } catch (IllegalAccessException ex) { throw ex; } catch (IllegalArgumentException ex) { throw ex; } catch (InvocationTargetException ex) { // It's a Result ? (expected) if (ex.getTargetException() instanceof Result) { throw (Result) ex.getTargetException(); } // Re-throw the enclosed exception if (ex.getTargetException() instanceof PlayException) { throw (PlayException) ex.getTargetException(); } StackTraceElement element = PlayException.getInterestingStackTraceElement(ex.getTargetException()); if (element != null) { throw new JavaExecutionException( Play.classes.getApplicationClass(element.getClassName()), element.getLineNumber(), ex.getTargetException()); } throw new JavaExecutionException(Http.Request.current().action, ex); } } catch (Result result) { Play.pluginCollection.onActionInvocationResult(result); // OK there is a result to apply // Save session & flash scope now Scope.Session.current().save(); Scope.Flash.current().save(); result.apply(request, response); Play.pluginCollection.afterActionInvocation(); // @Finally handleFinallies(request, null); } catch (PlayException e) { handleFinallies(request, e); throw e; } catch (Throwable e) { handleFinallies(request, e); throw new UnexpectedException(e); } finally { Play.pluginCollection.onActionInvocationFinally(); if (monitor != null) { monitor.stop(); } } }