@Override
  public void analyzeMethod(
      InjectionNode injectionNode,
      ASTType concreteType,
      ASTMethod astMethod,
      AnalysisContext context) {
    for (ASTAnnotation annotation : astMethod.getAnnotations()) {
      validateAnnotation(
          annotation, astMethod, astMethod.getAnnotations(), concreteType.getAnnotations());

      for (ASTParameter astParameter : astMethod.getParameters()) {
        validateParameter(astParameter, astMethod, concreteType);
      }
    }
  }
예제 #2
0
  private JExpression buildInterceptorChain(
      JDefinedClass definedClass,
      ASTMethod method,
      Map<ASTParameter, JVar> parameterMap,
      Set<InjectionNode> interceptors,
      Map<InjectionNode, JFieldVar> interceptorNameMap) {

    try {
      JDefinedClass methodExecutionClass =
          definedClass._class(
              JMod.PRIVATE | JMod.FINAL,
              namer.generateClassName(MethodInterceptorChain.MethodExecution.class));
      methodExecutionClass._implements(MethodInterceptorChain.MethodExecution.class);

      // setup constructor with needed parameters
      JMethod constructor = methodExecutionClass.constructor(JMod.PUBLIC);
      JBlock constructorbody = constructor.body();
      List<JExpression> methodParameters = new ArrayList<JExpression>();
      for (ASTParameter parameter : method.getParameters()) {
        JType parameterType = parameterMap.get(parameter).type();
        JVar param = constructor.param(parameterType, namer.generateName(parameterType));
        JFieldVar field =
            methodExecutionClass.field(
                JMod.PRIVATE, parameterType, namer.generateName(parameterType));
        constructorbody.assign(field, param);
        methodParameters.add(field);
      }

      // getMethod()
      JMethod getMethod =
          methodExecutionClass.method(
              JMod.PUBLIC, Method.class, MethodInterceptorChain.MethodExecution.GET_METHOD);

      JInvocation getMethodInvocation =
          definedClass.dotclass().invoke(CLASS_GET_METHOD).arg(method.getName());
      getMethod.body()._return(getMethodInvocation);
      getMethod._throws(NoSuchMethodException.class);

      for (ASTParameter astParameter : method.getParameters()) {
        getMethodInvocation.arg(codeModel.ref(astParameter.getASTType().getName()).dotclass());
      }

      // invoke()
      JMethod invokeMethod =
          methodExecutionClass.method(
              JMod.PUBLIC, Object.class, MethodInterceptorChain.MethodExecution.INVOKE);

      // add all throws of contained method
      for (ASTType throwable : method.getThrowsTypes()) {
        invokeMethod._throws(codeModel.ref(throwable.getName()));
      }

      JInvocation superCall = definedClass.staticRef(SUPER_REF).invoke(method.getName());

      for (JExpression methodParam : methodParameters) {
        superCall.arg(methodParam);
      }

      if (method.getReturnType().equals(ASTVoidType.VOID)) {
        invokeMethod.body().add(superCall);
        invokeMethod.body()._return(JExpr._null());
      } else {
        invokeMethod.body()._return(superCall);
      }

      JInvocation methodExecutionInvocation = JExpr._new(methodExecutionClass);

      for (ASTParameter astParameter : method.getParameters()) {
        methodExecutionInvocation.arg(parameterMap.get(astParameter));
      }

      JInvocation newInterceptorInvocation =
          JExpr._new(codeModel.ref(MethodInterceptorChain.class))
              .arg(methodExecutionInvocation)
              .arg(JExpr._this());

      for (InjectionNode interceptor : interceptors) {
        newInterceptorInvocation.arg(interceptorNameMap.get(interceptor));
      }

      return newInterceptorInvocation;
    } catch (JClassAlreadyExistsException e) {
      throw new TransfuseAnalysisException("Class already defined while generating inner class", e);
    }
  }
예제 #3
0
  private void buildMethodInterceptor(
      JDefinedClass definedClass,
      ConstructorInjectionPoint proxyConstructorInjectionPoint,
      JMethod constructor,
      JBlock constructorBody,
      Map<ASTMethod, Map<InjectionNode, JFieldVar>> interceptorFields,
      Map.Entry<ASTMethod, Set<InjectionNode>> methodInterceptorEntry)
      throws ClassNotFoundException {
    ASTMethod method = methodInterceptorEntry.getKey();

    if (method.getAccessModifier().equals(ASTAccessModifier.PRIVATE)) {
      throw new TransfuseAnalysisException("Unable to provide AOP on private methods");
    }

    if (!interceptorFields.containsKey(methodInterceptorEntry.getKey())) {
      interceptorFields.put(
          methodInterceptorEntry.getKey(), new HashMap<InjectionNode, JFieldVar>());
    }
    Map<InjectionNode, JFieldVar> injectionNodeInstanceNameMap =
        interceptorFields.get(methodInterceptorEntry.getKey());

    // setup interceptor fields
    for (InjectionNode interceptorInjectionNode : methodInterceptorEntry.getValue()) {
      String interceptorInstanceName = namer.generateName(interceptorInjectionNode);

      JFieldVar interceptorField =
          definedClass.field(
              JMod.PRIVATE,
              codeModel.ref(interceptorInjectionNode.getClassName()),
              interceptorInstanceName);

      injectionNodeInstanceNameMap.put(interceptorInjectionNode, interceptorField);

      JVar interceptorParam =
          constructor.param(
              codeModel.ref(interceptorInjectionNode.getClassName()),
              namer.generateName(interceptorInjectionNode));

      constructorBody.assign(interceptorField, interceptorParam);

      proxyConstructorInjectionPoint.addInjectionNode(interceptorInjectionNode);
    }

    JType returnType = codeModel.parseType(method.getReturnType().getName());

    JMethod methodDeclaration =
        definedClass.method(
            method.getAccessModifier().getCodeModelJMod(), returnType, method.getName());
    JBlock body = methodDeclaration.body();

    // define method parameter
    Map<ASTParameter, JVar> parameterMap = new HashMap<ASTParameter, JVar>();
    for (ASTParameter parameter : method.getParameters()) {
      parameterMap.put(
          parameter,
          methodDeclaration.param(
              JMod.FINAL,
              codeModel.ref(parameter.getASTType().getName()),
              namer.generateName(parameter.getASTType())));
    }

    // aop interceptor
    Map<InjectionNode, JFieldVar> interceptorNameMap =
        interceptorFields.get(methodInterceptorEntry.getKey());

    JArray paramArray = JExpr.newArray(codeModel.ref(Object.class));

    for (ASTParameter astParameter : method.getParameters()) {
      paramArray.add(parameterMap.get(astParameter));
    }

    JInvocation interceptorInvocation =
        buildInterceptorChain(
                definedClass,
                method,
                parameterMap,
                methodInterceptorEntry.getValue(),
                interceptorNameMap)
            .invoke("invoke");
    interceptorInvocation.arg(paramArray);

    if (method.getReturnType().equals(ASTVoidType.VOID)) {
      body.add(interceptorInvocation);
    } else {
      body._return(JExpr.cast(returnType.boxify(), interceptorInvocation));
    }
  }
예제 #4
0
 /**
  * Makes a descriptor for a given method.
  *
  * @param method
  * @return descriptor
  */
 private String makeDescriptor(ASTMethod method) {
   List<ASTParameter> params = method.getParameters();
   return method.getName() + ':' + makeDescriptor(params, method.getReturnType());
 }
  /**
   * gets an Object that 'is' the value of the reference
   *
   * @param o unused Object parameter
   * @param context context used to generate value
   * @return The execution result.
   * @throws MethodInvocationException
   */
  public Object execute(Object o, InternalContextAdapter context) throws MethodInvocationException {

    if (referenceType == RUNT) return null;

    /*
     *  get the root object from the context
     */

    Object result = getVariableValue(context, rootString);

    if (result == null && !strictRef) {
      //            return EventHandlerUtil.invalidGetMethod(rsvc, context,
      //                    getDollarBang() + rootString, null, null, uberInfo);
      return result;
    }

    /*
     * Iteratively work 'down' (it's flat...) the reference
     * to get the value, but check to make sure that
     * every result along the path is valid. For example:
     *
     * $hashtable.Customer.Name
     *
     * The $hashtable may be valid, but there is no key
     * 'Customer' in the hashtable so we want to stop
     * when we find a null value and return the null
     * so the error gets logged.
     */

    try {
      Object previousResult = result;
      int failedChild = -1;
      for (int i = 0; i < numChildren; i++) {
        if (strictRef && result == null) {
          /**
           * At this point we know that an attempt is about to be made to call a method or property
           * on a null value.
           */
          String name = jjtGetChild(i).getFirstToken().image;
          throw new VelocityException(
              "Attempted to access '"
                  + name
                  + "' on a null value at "
                  + Log.formatFileString(
                      uberInfo.getTemplateName(),
                      +jjtGetChild(i).getLine(),
                      jjtGetChild(i).getColumn()));
        }
        previousResult = result;
        result = jjtGetChild(i).execute(result, context);
        if (result == null && !strictRef) // If strict and null then well catch this
        // next time through the loop
        {
          failedChild = i;
          break;
        }
      }

      if (result == null) {
        if (failedChild == -1) {
          //                    result = EventHandlerUtil.invalidGetMethod(rsvc, context,
          //                            getDollarBang() + rootString, previousResult, null,
          // uberInfo);
        } else {
          StringBuffer name = new StringBuffer(getDollarBang()).append(rootString);
          for (int i = 0; i <= failedChild; i++) {
            Node node = jjtGetChild(i);
            if (node instanceof ASTMethod) {
              name.append(".").append(((ASTMethod) node).getMethodName()).append("()");
            } else {
              name.append(".").append(node.getFirstToken().image);
            }
          }

          if (jjtGetChild(failedChild) instanceof ASTMethod) {
            String methodName = ((ASTMethod) jjtGetChild(failedChild)).getMethodName();
            //                        result = EventHandlerUtil.invalidMethod(rsvc, context,
            //                                name.toString(), previousResult, methodName,
            // uberInfo);
          } else {
            String property = jjtGetChild(failedChild).getFirstToken().image;
            //                        result = EventHandlerUtil.invalidGetMethod(rsvc, context,
            //                                name.toString(), previousResult, property, uberInfo);
          }
        }
      }

      return result;
    } catch (MethodInvocationException mie) {
      mie.setReferenceName(rootString);
      throw mie;
    }
  }