Пример #1
0
  /**
   * Oracle's JDK8 encodes method references directly as an "invoke virtual" lambda. (Eclipse seems
   * to encode method references like a normal method). So here we handle this special case of an
   * "invoke virtual" lambda.
   */
  protected static MethodAnalysisResults analyzeInvokeVirtual(
      String methodClass,
      String methodName,
      String methodSignature,
      MetamodelUtil metamodel,
      ClassLoader alternateClassLoader,
      boolean isObjectEqualsSafe,
      boolean isCollectionContainsSafe,
      boolean throwExceptionOnFailure) {
    // See if the method call is allowed. Create a fake method argument that reroutes
    // to be the base of the method call.
    MethodSignature sig = new MethodSignature(methodClass, methodName, methodSignature);
    Type[] argTypes = Type.getMethodType(sig.desc).getArgumentTypes();
    MethodChecker checker =
        metamodel.getMethodChecker(isObjectEqualsSafe, isCollectionContainsSafe);
    TypedValue fakeBase = new TypedValue.ArgValue(sig.getOwnerType(), 0);
    List<TypedValue> fakeArgs = new ArrayList<>();
    for (int n = 0; n < argTypes.length; n++)
      fakeArgs.add(new TypedValue.ArgValue(argTypes[n], n + 1));
    if (OperationSideEffect.NONE != checker.isMethodSafe(sig, fakeBase, fakeArgs)) {
      if (throwExceptionOnFailure)
        throw new IllegalArgumentException(
            "Could not analyze lambda code. Unknown method " + sig + " encountered.");
      return null;
    }

    // Create a fake analysis of the methods that's composed of only a call to the given method.
    MethodCallValue.VirtualMethodCallValue methodCallVal =
        new MethodCallValue.VirtualMethodCallValue(
            sig.owner, sig.name, sig.desc, fakeArgs, fakeBase);
    MethodAnalysisResults analysis = new MethodAnalysisResults();
    analysis.addPath(new ArrayList<>(), methodCallVal, new ArrayList<>());

    return analysis;
  }
Пример #2
0
 /* (non-Javadoc)
  * @see ch.epfl.labos.iu.orm.queryll2.PathAnalysisMethodChecker#isMethodSafe(ch.epfl.labos.iu.orm.queryll2.symbolic.MethodSignature, ch.epfl.labos.iu.orm.queryll2.symbolic.TypedValue, java.util.List)
  */
 @Override
 public OperationSideEffect isMethodSafe(
     MethodSignature m, TypedValue base, List<TypedValue> args) {
   if (isObjectEqualsSafe && objectEquals.equals(m)) {
     return OperationSideEffect.NONE;
   } else if (safeMethods.contains(m)
       || subqueryMethods.contains(m)
       || jpqlFunctionMethods.contains(m)) {
     return OperationSideEffect.NONE;
   } else {
     // Use reflection to get info about the method (or would it be better
     // to do this through direct bytecode inspection?), and see if it's
     // annotated as safe
     try {
       Method reflectedMethod = Annotations.asmMethodSignatureToReflectionMethod(m);
       // Special handling of Collection.contains() for subclasses of Collection.
       if (isCollectionContainsSafe
           && "contains".equals(m.name)
           && "(Ljava/lang/Object;)Z".equals(m.desc)
           && Collection.class.isAssignableFrom(reflectedMethod.getDeclaringClass()))
         return OperationSideEffect.NONE;
       if (Annotations.methodHasSomeAnnotations(reflectedMethod, safeMethodAnnotations))
         return OperationSideEffect.NONE;
     } catch (ClassNotFoundException | NoSuchMethodException e) {
       // Eat the error
     }
     return OperationSideEffect.UNSAFE;
   }
 }
Пример #3
0
  static {
    try {
      // I'm initializing some of these method signatures through reflection
      // instead of statically so that it's easier to find breakages due to method renaming etc.
      jpqlLike =
          MethodSignature.fromMethod(JPQL.class.getMethod("like", String.class, String.class));
      jpqlIsIn =
          MethodSignature.fromMethod(JPQL.class.getMethod("isIn", Object.class, JinqStream.class));
      jpqlIsInList =
          MethodSignature.fromMethod(
              JPQL.class.getMethod("isInList", Object.class, Collection.class));
      jpqlListContains =
          MethodSignature.fromMethod(
              JPQL.class.getMethod("listContains", Collection.class, Object.class));

      streamSelectAll =
          MethodSignature.fromMethod(
              JinqStream.class.getMethod("selectAll", JinqStream.Join.class));
      streamSelectAllList =
          MethodSignature.fromMethod(
              JinqStream.class.getMethod("selectAllList", JinqStream.JoinToIterable.class));
      streamJoinList =
          MethodSignature.fromMethod(
              JinqStream.class.getMethod("joinList", JinqStream.JoinToIterable.class));
    } catch (NoSuchMethodException | SecurityException e) {
      throw new IllegalArgumentException(
          "Cannot initialize MethodChecker because it cannot find a needed method", e);
    }
  }