예제 #1
0
 public static Object invokeControllerMethod(Method method, Object[] forceArgs) throws Exception {
   if (Modifier.isStatic(method.getModifiers())
       && !method.getDeclaringClass().getName().matches("^controllers\\..*\\$class$")) {
     return invoke(
         method, null, forceArgs == null ? getActionMethodArgs(method, null) : forceArgs);
   } else if (Modifier.isStatic(method.getModifiers())) {
     Object[] args = getActionMethodArgs(method, null);
     args[0] = Http.Request.current().controllerClass.getDeclaredField("MODULE$").get(null);
     return invoke(method, null, args);
   } else {
     Object instance = null;
     try {
       instance = method.getDeclaringClass().getDeclaredField("MODULE$").get(null);
     } catch (Exception e) {
       Annotation[] annotations = method.getDeclaredAnnotations();
       String annotation = Utils.getSimpleNames(annotations);
       if (!StringUtils.isEmpty(annotation)) {
         throw new UnexpectedException(
             "Method public static void "
                 + method.getName()
                 + "() annotated with "
                 + annotation
                 + " in class "
                 + method.getDeclaringClass().getName()
                 + " is not static.");
       }
       // TODO: Find a better error report
       throw new ActionNotFoundException(Http.Request.current().action, e);
     }
     return invoke(
         method, instance, forceArgs == null ? getActionMethodArgs(method, instance) : forceArgs);
   }
 }
예제 #2
0
  // Gets baseUrl from current request or application.baseUrl in application.conf
  protected static String getBaseUrl() {
    if (Http.Request.current() == null) {
      // No current request is present - must get baseUrl from config
      String appBaseUrl =
          Play.configuration.getProperty("application.baseUrl", "application.baseUrl");
      if (appBaseUrl.endsWith("/")) {
        // remove the trailing slash
        appBaseUrl = appBaseUrl.substring(0, appBaseUrl.length() - 1);
      }
      return appBaseUrl;

    } else {
      return Http.Request.current().getBase();
    }
  }
예제 #3
0
파일: UserApp.java 프로젝트: bluemir/hive
  /**
   * 현재 사용자가 선호하는 언어를 갱신한다.
   *
   * <p>쿠키나 Accept-Language HTTP 헤더에 선호하는 언어가 설정되어 있는 경우, 그것을 현재 로그인한 사용자가 선호하는 언어로 설정한다.
   */
  public static void updatePreferredLanguage() {
    Http.Request request = Http.Context.current().request();
    User user = UserApp.currentUser();

    if (user.isAnonymous()) {
      return;
    }

    if (request.acceptLanguages().isEmpty() && request.cookie(Play.langCookieName()) == null) {
      return;
    }

    String code = StringUtils.left(Http.Context.current().lang().code(), 255);

    if (!code.equals(user.lang)) {
      user.lang = code;
      user.update();
    }
  }
예제 #4
0
 public void absolute() {
   boolean isSecure = Http.Request.current() == null ? false : Http.Request.current().secure;
   String base = getBaseUrl();
   String hostPart = host;
   String domain = Http.Request.current() == null ? "" : Http.Request.current().get().domain;
   int port = Http.Request.current() == null ? 80 : Http.Request.current().get().port;
   if (port != 80 && port != 443) {
     hostPart += ":" + port;
   }
   // ~
   if (!url.startsWith("http")) {
     if (StringUtils.isEmpty(host)) {
       url = base + url;
     } else if (host.contains("{_}")) {
       java.util.regex.Matcher matcher =
           java.util.regex.Pattern.compile("([-_a-z0-9A-Z]+([.][-_a-z0-9A-Z]+)?)$")
               .matcher(domain);
       if (matcher.find()) {
         url =
             (isSecure ? "https://" : "http://")
                 + hostPart.replace("{_}", matcher.group(1))
                 + url;
       } else {
         url = (isSecure ? "https://" : "http://") + hostPart + url;
       }
     } else {
       url = (isSecure ? "https://" : "http://") + hostPart + url;
     }
     if (method.equals("WS")) {
       url = url.replaceFirst("https?", "ws");
     }
   }
 }
예제 #5
0
 public static String reverse(VirtualFile file, boolean absolute) {
   if (file == null || !file.exists()) {
     throw new NoRouteFoundException("File not found (" + file + ")");
   }
   String path = file.relativePath();
   path = path.substring(path.indexOf("}") + 1);
   for (Route route : routes) {
     String staticDir = route.staticDir;
     if (staticDir != null) {
       if (!staticDir.startsWith("/")) {
         staticDir = "/" + staticDir;
       }
       if (!staticDir.equals("/") && !staticDir.endsWith("/")) {
         staticDir = staticDir + "/";
       }
       if (path.startsWith(staticDir)) {
         String to = route.path + path.substring(staticDir.length());
         if (to.endsWith("/index.html")) {
           to = to.substring(0, to.length() - "/index.html".length() + 1);
         }
         if (absolute) {
           boolean isSecure =
               Http.Request.current() == null ? false : Http.Request.current().secure;
           String base = getBaseUrl();
           if (!StringUtils.isEmpty(route.host)) {
             // Compute the host
             int port = Http.Request.current() == null ? 80 : Http.Request.current().get().port;
             String host = (port != 80 && port != 443) ? route.host + ":" + port : route.host;
             to = (isSecure ? "https://" : "http://") + host + to;
           } else {
             to = base + to;
           }
         }
         return to;
       }
     }
   }
   throw new NoRouteFoundException(file.relativePath());
 }
예제 #6
0
  @SuppressWarnings("unchecked")
  public static void resolve(Http.Request request, Http.Response response) {

    if (!Play.started) {
      return;
    }

    Http.Request.current.set(request);
    Http.Response.current.set(response);

    Scope.Params.current.set(request.params);
    Scope.RenderArgs.current.set(new Scope.RenderArgs());
    Scope.RouteArgs.current.set(new Scope.RouteArgs());
    Scope.Session.current.set(Scope.Session.restore());
    Scope.Flash.current.set(Scope.Flash.restore());
    CachedBoundActionMethodArgs.init();

    ControllersEnhancer.currentAction.set(new Stack<String>());

    if (request.resolved) {
      return;
    }

    // Route and resolve format if not already done
    if (request.action == null) {
      Play.pluginCollection.routeRequest(request);
      Route route = Router.route(request);
      Play.pluginCollection.onRequestRouting(route);
    }
    request.resolveFormat();

    // Find the action method
    try {
      Method actionMethod = null;
      Object[] ca = getActionMethod(request.action);
      actionMethod = (Method) ca[1];
      request.controller = ((Class) ca[0]).getName().substring(12).replace("$", "");
      request.controllerClass = ((Class) ca[0]);
      request.actionMethod = actionMethod.getName();
      request.action = request.controller + "." + request.actionMethod;
      request.invokedMethod = actionMethod;

      if (Logger.isTraceEnabled()) {
        Logger.trace("------- %s", actionMethod);
      }

      request.resolved = true;

    } catch (ActionNotFoundException e) {
      Logger.error(e, "%s action not found", e.getAction());
      throw new NotFound(String.format("%s action not found", e.getAction()));
    }
  }
예제 #7
0
 public static Route route(Http.Request request) {
   if (Logger.isTraceEnabled()) {
     Logger.trace("Route: " + request.path + " - " + request.querystring);
   }
   // request method may be overriden if a x-http-method-override parameter is given
   if (request.querystring != null && methodOverride.matches(request.querystring)) {
     Matcher matcher = methodOverride.matcher(request.querystring);
     if (matcher.matches()) {
       if (Logger.isTraceEnabled()) {
         Logger.trace(
             "request method %s overriden to %s ", request.method, matcher.group("method"));
       }
       request.method = matcher.group("method");
     }
   }
   for (Route route : routes) {
     Map<String, String> args =
         route.matches(request.method, request.path, request.format, request.domain);
     if (args != null) {
       request.routeArgs = args;
       request.action = route.action;
       if (args.containsKey("format")) {
         request.format = args.get("format");
       }
       if (request.action.indexOf("{") > -1) { // more optimization ?
         for (String arg : request.routeArgs.keySet()) {
           request.action = request.action.replace("{" + arg + "}", request.routeArgs.get(arg));
         }
       }
       if (request.action.equals("404")) {
         throw new NotFound(route.path);
       }
       return route;
     }
   }
   // Not found - if the request was a HEAD, let's see if we can find a corresponding GET
   if (request.method.equalsIgnoreCase("head")) {
     request.method = "GET";
     Route route = route(request);
     request.method = "HEAD";
     if (route != null) {
       return route;
     }
   }
   throw new NotFound(request.method, request.path);
 }
예제 #8
0
  public static ActionDefinition reverse(String action, Map<String, Object> args) {

    String encoding =
        Http.Response.current() == null
            ? Play.defaultWebEncoding
            : Http.Response.current().encoding;

    if (action.startsWith("controllers.")) {
      action = action.substring(12);
    }
    Map<String, Object> argsbackup = new HashMap<String, Object>(args);
    // Add routeArgs
    if (Scope.RouteArgs.current() != null) {
      for (String key : Scope.RouteArgs.current().data.keySet()) {
        if (!args.containsKey(key)) {
          args.put(key, Scope.RouteArgs.current().data.get(key));
        }
      }
    }
    for (Route route : routes) {
      if (route.actionPattern != null) {
        Matcher matcher = route.actionPattern.matcher(action);
        if (matcher.matches()) {
          for (String group : route.actionArgs) {
            String v = matcher.group(group);
            if (v == null) {
              continue;
            }
            args.put(group, v.toLowerCase());
          }
          List<String> inPathArgs = new ArrayList<String>(16);
          boolean allRequiredArgsAreHere = true;
          // les noms de parametres matchent ils ?
          for (Route.Arg arg : route.args) {
            inPathArgs.add(arg.name);
            Object value = args.get(arg.name);
            if (value == null) {
              // This is a hack for reverting on hostname that are a regex expression.
              // See [#344] for more into. This is not optimal and should retough. However,
              // it allows us to do things like {(.*}}.domain.com
              String host = route.host.replaceAll("\\{", "").replaceAll("\\}", "");
              if (host.equals(arg.name) || host.matches(arg.name)) {
                args.remove(arg.name);
                route.host = Http.Request.current() == null ? "" : Http.Request.current().domain;
                break;
              } else {
                allRequiredArgsAreHere = false;
                break;
              }
            } else {
              if (value instanceof List<?>) {
                @SuppressWarnings("unchecked")
                List<Object> l = (List<Object>) value;
                value = l.get(0);
              }
              if (!value.toString().startsWith(":") && !arg.constraint.matches(value.toString())) {
                allRequiredArgsAreHere = false;
                break;
              }
            }
          }
          // les parametres codes en dur dans la route matchent-ils ?
          for (String staticKey : route.staticArgs.keySet()) {
            if (staticKey.equals("format")) {
              if (!(Http.Request.current() == null ? "" : Http.Request.current().format)
                  .equals(route.staticArgs.get("format"))) {
                allRequiredArgsAreHere = false;
                break;
              }
              continue; // format is a special key
            }
            if (!args.containsKey(staticKey)
                || (args.get(staticKey) == null)
                || !args.get(staticKey).toString().equals(route.staticArgs.get(staticKey))) {
              allRequiredArgsAreHere = false;
              break;
            }
          }
          if (allRequiredArgsAreHere) {
            StringBuilder queryString = new StringBuilder();
            String path = route.path;
            String host = route.host;
            if (path.endsWith("/?")) {
              path = path.substring(0, path.length() - 2);
            }
            for (Map.Entry<String, Object> entry : args.entrySet()) {
              String key = entry.getKey();
              Object value = entry.getValue();
              if (inPathArgs.contains(key) && value != null) {
                if (List.class.isAssignableFrom(value.getClass())) {
                  @SuppressWarnings("unchecked")
                  List<Object> vals = (List<Object>) value;
                  path =
                      path.replaceAll("\\{(<[^>]+>)?" + key + "\\}", vals.get(0).toString())
                          .replace("$", "\\$");
                } else {
                  path =
                      path.replaceAll(
                          "\\{(<[^>]+>)?" + key + "\\}",
                          value
                              .toString()
                              .replace("$", "\\$")
                              .replace("%3A", ":")
                              .replace("%40", "@"));
                  host =
                      host.replaceAll(
                          "\\{(<[^>]+>)?" + key + "\\}",
                          value
                              .toString()
                              .replace("$", "\\$")
                              .replace("%3A", ":")
                              .replace("%40", "@"));
                }
              } else if (route.staticArgs.containsKey(key)) {
                // Do nothing -> The key is static
              } else if (Scope.RouteArgs.current() != null
                  && Scope.RouteArgs.current().data.containsKey(key)) {
                // Do nothing -> The key is provided in RouteArgs and not used (see #447)
              } else if (value != null) {
                if (List.class.isAssignableFrom(value.getClass())) {
                  @SuppressWarnings("unchecked")
                  List<Object> vals = (List<Object>) value;
                  for (Object object : vals) {
                    try {
                      queryString.append(URLEncoder.encode(key, encoding));
                      queryString.append("=");
                      if (object.toString().startsWith(":")) {
                        queryString.append(object.toString());
                      } else {
                        queryString.append(URLEncoder.encode(object.toString() + "", encoding));
                      }
                      queryString.append("&");
                    } catch (UnsupportedEncodingException ex) {
                    }
                  }
                } else if (value.getClass().equals(Default.class)) {
                  // Skip defaults in queryString
                } else {
                  try {
                    queryString.append(URLEncoder.encode(key, encoding));
                    queryString.append("=");
                    if (value.toString().startsWith(":")) {
                      queryString.append(value.toString());
                    } else {
                      queryString.append(URLEncoder.encode(value.toString() + "", encoding));
                    }
                    queryString.append("&");
                  } catch (UnsupportedEncodingException ex) {
                  }
                }
              }
            }
            String qs = queryString.toString();
            if (qs.endsWith("&")) {
              qs = qs.substring(0, qs.length() - 1);
            }
            ActionDefinition actionDefinition = new ActionDefinition();
            actionDefinition.url = qs.length() == 0 ? path : path + "?" + qs;
            actionDefinition.method =
                route.method == null || route.method.equals("*")
                    ? "GET"
                    : route.method.toUpperCase();
            actionDefinition.star = "*".equals(route.method);
            actionDefinition.action = action;
            actionDefinition.args = argsbackup;
            actionDefinition.host = host;
            return actionDefinition;
          }
        }
      }
    }
    throw new NoRouteFoundException(action, args);
  }
예제 #9
0
  static Object invokeWithContinuation(Method method, Object instance, Object[] realArgs)
      throws Exception {
    // Callback case
    if (Http.Request.current().args.containsKey(A)) {

      // Action0
      instance = Http.Request.current().args.get(A);
      Future f = (Future) Http.Request.current().args.get(F);
      Scope.RenderArgs renderArgs =
          (Scope.RenderArgs)
              Request.current().args.remove(ActionInvoker.CONTINUATIONS_STORE_RENDER_ARGS);
      Scope.RenderArgs.current.set(renderArgs);
      if (f == null) {
        method = instance.getClass().getDeclaredMethod("invoke");
        method.setAccessible(true);
        return method.invoke(instance);
      } else {
        method = instance.getClass().getDeclaredMethod("invoke", Object.class);
        method.setAccessible(true);
        return method.invoke(instance, f.get());
      }
    }

    // Continuations case
    Continuation continuation = (Continuation) Http.Request.current().args.get(C);
    if (continuation == null) {
      continuation = new Continuation(new StackRecorder((Runnable) null));
    }

    StackRecorder pStackRecorder = new StackRecorder(continuation.stackRecorder);
    Object result = null;

    final StackRecorder old = pStackRecorder.registerThread();
    try {
      pStackRecorder.isRestoring = !pStackRecorder.isEmpty();

      // Execute code
      result = method.invoke(instance, realArgs);

      if (pStackRecorder.isCapturing) {
        if (pStackRecorder.isEmpty()) {
          throw new IllegalStateException(
              "stack corruption. Is " + method + " instrumented for javaflow?");
        }
        Object trigger = pStackRecorder.value;
        Continuation nextContinuation = new Continuation(pStackRecorder);
        Http.Request.current().args.put(C, nextContinuation);

        if (trigger instanceof Long) {
          throw new Suspend((Long) trigger);
        }
        if (trigger instanceof Integer) {
          throw new Suspend(((Integer) trigger).longValue());
        }
        if (trigger instanceof Future) {
          throw new Suspend((Future) trigger);
        }

        throw new UnexpectedException("Unexpected continuation trigger -> " + trigger);
      } else {
        Http.Request.current().args.remove(C);
      }
    } finally {
      pStackRecorder.deregisterThread(old);
    }

    return result;
  }
예제 #10
0
  /**
   * 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);
      Collections.sort(
          allFinally,
          new Comparator<Method>() {

            public int compare(Method m1, Method m2) {
              Finally finally1 = m1.getAnnotation(Finally.class);
              Finally finally2 = m2.getAnnotation(Finally.class);
              return finally1.priority() - finally2.priority();
            }
          });
      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.getInterestingStrackTraceElement(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);
    }
  }
예제 #11
0
  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) {
        Controller.class.getDeclaredField("params").set(null, Scope.Params.current());
        Controller.class.getDeclaredField("request").set(null, Http.Request.current());
        Controller.class.getDeclaredField("response").set(null, Http.Response.current());
        Controller.class.getDeclaredField("session").set(null, Scope.Session.current());
        Controller.class.getDeclaredField("flash").set(null, Scope.Flash.current());
        Controller.class.getDeclaredField("renderArgs").set(null, Scope.RenderArgs.current());
        Controller.class.getDeclaredField("routeArgs").set(null, Scope.RouteArgs.current());
        Controller.class.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 (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);
              Collections.sort(
                  catches,
                  new Comparator<Method>() {

                    public int compare(Method m1, Method m2) {
                      Catch catch1 = m1.getAnnotation(Catch.class);
                      Catch catch2 = m2.getAnnotation(Catch.class);
                      return catch1.priority() - catch2.priority();
                    }
                  });
              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.getInterestingStrackTraceElement(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 {
      if (monitor != null) {
        monitor.stop();
      }
    }
  }