Package cn.bran.play.routing

Source Code of cn.bran.play.routing.RouterUtils

/**
*
*/
package cn.bran.play.routing;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HEAD;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;

import org.reflections.ReflectionUtils;

import play.libs.F.Tuple;

import com.google.common.base.Predicates;

/**
* @author bran
*
*/
public class RouterUtils {

  // old perhaps incorrect impl. was looking for subgroups
  // static List<String> findAllIn(Pattern p, String string) {
  // List<String> ret = new ArrayList<String>();
  // Matcher matcher = p.matcher(string);
  // while (matcher.find()) {
  // int c = matcher.groupCount();
  // for (int i = 1; i <= c; i++) {
  // String group = matcher.group(i);
  // ret.add(group);
  // }
  // }
  // return ret;
  // }
  //
  // find class level annotation
  /**
   * find if the uri contains variables
   *
   * @author Bing Ran (bing.ran@gmail.com)
   * @param uri
   * @param path
   * @return true if it contains, false otherwise
   */
  static boolean isResourcePath(String uri, String path) {
    String r = path.replaceAll(JaxrsRouter.urlParamCapture, "(.*)");
    Pattern p = Pattern.compile(r);
    if (!RegMatch.findAllIn(p, uri).isEmpty())
      return true;
    else
      return false;
  }

  static Class<? extends Annotation> findHttpMethodAnnotation(String httpMethod) {
    if (httpMethod.equals("GET"))
      return GET.class;
    else if (httpMethod.equals("POST"))
      return POST.class;
    else if (httpMethod.equals("POST"))
      return POST.class;
    else if (httpMethod.equals("PUT"))
      return PUT.class;
    else if (httpMethod.equals("DELETE"))
      return DELETE.class;
    else if (httpMethod.equals("HEAD"))
      return HEAD.class;
    else if (httpMethod.equals("OPTIONS"))
      return OPTIONS.class;
    else
      return null;
  }

  static TargetClassWithPath findLongestMatch(Set<Class<?>> classes, play.mvc.Http.RequestHeader reqHeader,
      String appPath) {
    TargetClassWithPath ret = null;
    String rpath = reqHeader.path();
    for (Class<?> c : classes) {
      String path = appPath + JaxrsRouter.prefixSlash(c.getAnnotation(Path.class).value());
      if (isResourcePath(rpath, path)) {
        if (ret == null || path.length() > ret._2().length()) {
          ret = new TargetClassWithPath(c, path);
        }
      }
    }
    return ret;
  }

  static RouterClass findLongestMatch(List<RouterClass> classes, play.mvc.Http.RequestHeader reqHeader) {
    RouterClass ret = null;
    String rpath = reqHeader.path();
    for (RouterClass c : classes) {
      if (!RegMatch.findAllIn(c.absPathPatternForValues, rpath).isEmpty())
        if (ret == null || c.absPath.length() > ret.absPath.length()) {
          ret = c;
        }
    }
    return ret;
  }

  static java.util.Set<Method> relevantMethods(Class<?> c, Class<? extends Annotation> a) {
    return ReflectionUtils.getAllMethods(c, Predicates.and(ReflectionUtils.withAnnotation(a)));
  }

  /**
   *
   * @author Bing Ran (bing.ran@gmail.com)
   * @param rootPath
   * @param uri
   * @param methods
   * @param contentType
   * @return a tuple of method and its param name-value map
   */
  static Tuple<Method, Map<String, String>> findMethodAndGenerateContext(String rootPath, String uri,
      java.util.Set<Method> methods, String contentType) {
    // include rootPath only for non root slash class level @Path values or
    // if the uri is root slash
    String[] consumeTypes = new String[] { contentType };
    String rootPathPrefix = (rootPath == "/" && uri != "/") ? "" : rootPath;

    for (Method m : methods) {

      Consumes consumes = m.getAnnotation(Consumes.class);
      if (consumes != null) {
        consumeTypes = consumes.value();
      }

      boolean contained = false;
      for (String c : consumeTypes) {
        if (c.equals(contentType)) {
          contained = true;
          break;
        }
      }
      if (contained) {
        Path p = m.getAnnotation(Path.class);
        String mPath = p == null ? "" : JaxrsRouter.prefixSlash(p.value());
        String fullMethodPath = (rootPathPrefix + mPath).replace("//", "/");

        // List<String> matches =
        // RegMatch.findAllIn(Pattern.compile(fullMethodPath), uri );
        // if (matches.size() > 0) {
        // matches = RegMatch.findAllIn(Pattern.compile(uri),
        // fullMethodPath);
        // if (matches.size() > 0) {
        // return new Tuple<Method, Map<String, String>>(m, new
        // HashMap<String, String>());
        // }
        // }

        // bran let's do exact match
        if (uri.equals(fullMethodPath)) {
          return new Tuple<Method, Map<String, String>>(m, new HashMap<String, String>());
        } else // any variables?
        if (fullMethodPath.contains("{") && fullMethodPath.contains("}")) {
          String combinedReg = fullMethodPath.replaceAll(JaxrsRouter.urlParamCapture, "\\\\{(.*)\\\\}");// .r;
          Pattern r = Pattern.compile(combinedReg);
          List<RegMatch> rootParamNameMatches = RegMatch.findAllMatchesIn(r, fullMethodPath);
          List<String> rootParamNames = new ArrayList<String>();
          for (RegMatch rm : rootParamNameMatches) {
            rootParamNames.addAll(rm.subgroups);
          }

          combinedReg = fullMethodPath.replaceAll(JaxrsRouter.urlParamCapture, "(.*)");
          r = Pattern.compile(combinedReg);
          List<RegMatch> rootParamValueMatches = RegMatch.findAllMatchesIn(r, uri);
          List<String> rootParamValues = new ArrayList<String>();
          for (RegMatch rm : rootParamValueMatches) {
            rootParamValues.addAll(rm.subgroups);
          }

          Map<String, String> methodMetaData = new java.util.HashMap<String, String>();
          int c = 0;
          for (String name : rootParamNames) {
            try {
              methodMetaData.put(name, rootParamValues.get(c++));
            } catch (Exception e) {
              methodMetaData.put(name, "");
            }
          }

          if (rootParamValues.size() > 0) {
            return new Tuple<Method, Map<String, String>>(m, methodMetaData);
          }
        }
      }
    }
    return null;
  }
 
  static play.mvc.Result invokeMethod(Class<?> targetClass, play.GlobalSettings global, Method method,
      Map<String, Object> extractedArgs, play.mvc.Http.RequestHeader r) {
    try {
      Object[] argValues = new Object[0];
      List<Object> argVals = new ArrayList<Object>();
      Annotation[][] annos = method.getParameterAnnotations();

      for (Annotation[] ans : annos) {
        PathParam pathParam = null;
        QueryParam queryParam = null;

        for (Annotation an : ans) {
          if (an instanceof PathParam)
            pathParam = (PathParam) an;
          else if (an instanceof QueryParam)
            queryParam = (QueryParam) an;
        }
        if (pathParam != null) {
          Object v = extractedArgs.get(pathParam.value());
          if (v != null)
            argVals.add(v);
          else
            throw new IllegalArgumentException("can not find annotation value for argument "
                + pathParam.value() + "in " + targetClass + "#" + method);
        } else if (queryParam != null) {
          String queryString = r.getQueryString(queryParam.value());
          argVals.add(queryString); // string type conversion?
        } else
          throw new IllegalArgumentException(
              "can not find an appropriate JAX-RC annotation for an argument for method:" + targetClass
                  + "#" + method);
      }
      argValues = argVals.toArray(argValues);
      return (play.mvc.Result) method.invoke(global.getControllerInstance(targetClass), argValues);
    } catch (InvocationTargetException cause) {
      System.err.println("Exception occured while trying to invoke: " + targetClass.getName() + "#"
          + method.getName() + " with " + extractedArgs + " for uri:" + r.path());
      throw new RuntimeException(cause.getCause());
    } catch (Exception e) {
      throw new RuntimeException(e.getCause());
    }
  }

  static Set<Class<?>> classes(ClassLoader parentClassloader) {
    return JaxrsRouter.getControllersWithPath();
//    Set<String> typesAnnotatedWith = JaxrsRouter.ref.getStore().getTypesAnnotatedWith(Path.class.getName());
//    Set<Class<?>> clazz = new HashSet<Class<?>>();
//    for (String t : typesAnnotatedWith) {
//      try {
//        clazz.add(Class.forName(t, true, parentClassloader));
//      } catch (ClassNotFoundException e) {
////        throw new RuntimeException(e);
//      }
//    }
//    return clazz;
  }

}
TOP

Related Classes of cn.bran.play.routing.RouterUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.