Package com.gwtent.aop.matcher

Source Code of com.gwtent.aop.matcher.AspectJExpress

/*******************************************************************************
*  Copyright 2001, 2007 JamesLuo(JamesLuo.au@gmail.com)
*  Licensed under the Apache License, Version 2.0 (the "License"); you may not
*  use this file except in compliance with the License. You may obtain a copy of
*  the License at
*  http://www.apache.org/licenses/LICENSE-2.0
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
*  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
*  License for the specific language governing permissions and limitations under
*  the License.
*
*  Contributors:
*******************************************************************************/
package com.gwtent.aop.matcher;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.aspectj.weaver.BCException;
import org.aspectj.weaver.reflect.ReflectionWorld;
import org.aspectj.weaver.tools.ContextBasedMatcher;
import org.aspectj.weaver.tools.FuzzyBoolean;
import org.aspectj.weaver.tools.MatchingContext;
import org.aspectj.weaver.tools.PointcutDesignatorHandler;
import org.aspectj.weaver.tools.PointcutExpression;
import org.aspectj.weaver.tools.PointcutParameter;
import org.aspectj.weaver.tools.PointcutParser;
import org.aspectj.weaver.tools.PointcutPrimitive;
import org.aspectj.weaver.tools.ShadowMatch;

import com.gwtent.aop.ClassFilter;
import com.gwtent.aop.Pointcut;
import com.gwtent.common.client.CheckedExceptionWrapper;


public class AspectJExpress implements Pointcut, ClassFilter, com.gwtent.aop.MethodMatcher {

  private static final Set<PointcutPrimitive> DEFAULT_SUPPORTED_PRIMITIVES = new HashSet<PointcutPrimitive>();

  static {
    DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
    DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.ARGS);
    DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.REFERENCE);
    DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.THIS);
    DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.TARGET);
    DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.WITHIN);
    DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ANNOTATION);
    DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_WITHIN);
    DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ARGS);
    DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_TARGET);
  }

  private String expression;
 
  private final Map<Method, ShadowMatch> shadowMapCache = new HashMap<Method, ShadowMatch>();
  
  private PointcutParser pointcutParser;

  private Class<?> pointcutDeclarationScope;

  private String[] pointcutParameterNames = new String[0];

  private Class[] pointcutParameterTypes = new Class[0];

  private PointcutExpression pointcutExpression;
 
  private final Set<ClassMethodMatcher> methodMatchers = new HashSet<ClassMethodMatcher>();

 
  public AspectJExpress(){
    this.pointcutParser =
      PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(
          DEFAULT_SUPPORTED_PRIMITIVES);
    this.pointcutParser.registerPointcutDesignatorHandler(new MatchClassPointcutDesignatorHandler());
  }
 
  public AspectJExpress(String expression){
    this();
    this.setExpression(expression);
  }
 
 
  public String toString() {
    StringBuffer sb = new StringBuffer();
    sb.append("AspectJExpressionPointcut: ");
    if (this.pointcutParameterNames != null && this.pointcutParameterTypes != null) {
      sb.append("(");
      for (int i = 0; i < this.pointcutParameterTypes.length; i++) {
        sb.append(this.pointcutParameterTypes[i].getName());
        sb.append(" ");
        sb.append(this.pointcutParameterNames[i]);
        if ((i+1) < this.pointcutParameterTypes.length) {
          sb.append(", ");
        }
      }
      sb.append(")");
    }
    sb.append(" ");
    if (getExpression() != null) {
      sb.append(getExpression());
    }
    else {
      sb.append("<pointcut expression not set>");
    }
    return sb.toString();
  }
 
  public void setExpression(String expression) {
    this.expression = expression;
  }


  public String getExpression() {
    return expression;
  }
 
  /**
   * Return the underlying AspectJ pointcut expression.
   */
  public PointcutExpression getPointcutExpression() {
    checkReadyToMatch();
    return this.pointcutExpression;
  }


  public boolean matches(Class<?> targetClass) {
    checkReadyToMatch();
    boolean result = false;
    try {
      result = this.pointcutExpression.couldMatchJoinPointsInType(targetClass);
    }
    catch (BCException ex) {
      //logger.debug("PointcutExpression matching rejected target class", ex);
      result = false;
    }
   
    if (result)
      return result;
    else{
      return matchesByClassMatcher(targetClass) != null;
   
  }

  public boolean isRuntime() {
    checkReadyToMatch();
    return this.pointcutExpression.mayNeedDynamicTest();
  }

  public boolean matches(Method method, Class<?> targetClass, Object... args) {
    checkReadyToMatch();
//    ShadowMatch shadowMatch = null;
    ShadowMatch originalShadowMatch = null;
    try {
      //shadowMatch = getShadowMatch(AopUtils.getMostSpecificMethod(method, targetClass), method);
      originalShadowMatch = getShadowMatch(method, method);
      if (originalShadowMatch.alwaysMatches())
        return true;
      else
        return matchesByMethodMatcher(method, targetClass, args);
       
    }
    catch (ReflectionWorld.ReflectionWorldException ex) {
      // Could neither introspect the target class nor the proxy class ->
      // let's simply consider this method as non-matching.
      return false;
    }
  }

  void addMethodMatcher(ClassMethodMatcher methodMatcher){
    methodMatchers.add(methodMatcher);
  }
 
  /**
   *
   * @param clazz
   * @return if matcher, return MethodMatcher, otherwise return null
   */
  private ClassMethodMatcher matchesByClassMatcher(Class<?> clazz){
    for (ClassMethodMatcher methodMatcher : methodMatchers){
      if (methodMatcher.getClassMatcher().matches(clazz))
        return methodMatcher;
    }
    return null;
  }
 
  private boolean matchesByMethodMatcher(Method method, Class<?> clazz, Object[] args){
    ClassMethodMatcher methodMatcher = matchesByClassMatcher(clazz);
    if (methodMatcher != null){
      return methodMatcher.getMethodMatcher().matches(method);
    }
   
    return false;
  }
 
  private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
    synchronized (this.shadowMapCache) {
      ShadowMatch shadowMatch = (ShadowMatch) this.shadowMapCache.get(targetMethod);
      if (shadowMatch == null) {
        try {
          shadowMatch = this.pointcutExpression.matchesMethodExecution(targetMethod);
        }
        catch (ReflectionWorld.ReflectionWorldException ex) {
          // Failed to introspect target method, probably because it has been loaded
          // in a special ClassLoader. Let's try the original method instead...
          if (targetMethod == originalMethod) {
            throw ex;
          }
          shadowMatch = this.pointcutExpression.matchesMethodExecution(originalMethod);
        }
        this.shadowMapCache.put(targetMethod, shadowMatch);
      }
      return shadowMatch;
    }
  }

 
  /**
   * Check whether this pointcut is ready to match,
   * lazily building the underlying AspectJ pointcut expression.
   */
  private void checkReadyToMatch() {
    if (getExpression() == null) {
      throw new IllegalStateException("Must set property 'expression' before attempting to match");
    }
    if (this.pointcutExpression == null) {
      this.pointcutExpression = buildPointcutExpression();
    }
  }
 
  /**
   * Build the underlying AspectJ pointcut expression.
   */
  private PointcutExpression buildPointcutExpression() {
    PointcutParameter[] pointcutParameters = new PointcutParameter[this.pointcutParameterNames.length];
    for (int i = 0; i < pointcutParameters.length; i++) {
      pointcutParameters[i] = this.pointcutParser.createPointcutParameter(
          this.pointcutParameterNames[i], this.pointcutParameterTypes[i]);
    }
    return this.pointcutParser.parsePointcutExpression(
        getExpression(), this.pointcutDeclarationScope, pointcutParameters);
  }


  private class MatchClassPointcutDesignatorHandler implements PointcutDesignatorHandler {

    private static final String MATCHCLASS_DESIGNATOR_NAME = "matchclass";

    public String getDesignatorName() {
      return MATCHCLASS_DESIGNATOR_NAME;
    }

    public ContextBasedMatcher parse(String expression) {
      return new MatchClassContextMatcher(expression);
    }
  }
 
  private class MatchClassContextMatcher implements ContextBasedMatcher {

    private final String matchClassName;
    private final ClassMethodMatcher matcher;
    private final Matcher<? super Class<?>> classMatcher;
    //private final Matcher<? super Method> methodMatcher;

    public MatchClassContextMatcher(String matchClassName) {
      this.matchClassName = matchClassName;
      this.matcher = getMatcherClass();
      classMatcher = matcher.getClassMatcher();
      //methodMatcher = matcher.getMethodMatcher();
      AspectJExpress.this.addMethodMatcher(matcher);
    }

    @SuppressWarnings("unchecked")
    public boolean couldMatchJoinPointsInType(Class someClass) {
      Class<?> clazz = someClass;
      return classMatcher.matches(clazz);
      //return true;
    }

    @SuppressWarnings("unchecked")
    public boolean couldMatchJoinPointsInType(Class someClass, MatchingContext context) {
      Class<?> clazz = someClass;
      return classMatcher.matches(clazz);
    }

    public boolean matchesDynamically(MatchingContext context) {
      return true;
    }

    public FuzzyBoolean matchesStatically(MatchingContext context) {
      return contextMatch();
    }

    public boolean mayNeedDynamicTest() {
      return false;
    }

    private FuzzyBoolean contextMatch() {
//      String advisedBeanName = getCurrentProxiedBeanName();
//      if (advisedBeanName == null) { // no proxy creation in progress
//        // abstain; can't return YES, since that will make pointcut with negation fail
//        return FuzzyBoolean.MAYBE;
//      }
//      if (BeanFactoryUtils.isGeneratedBeanName(advisedBeanName)) {
//        return FuzzyBoolean.NO;
//      }
//      if (this.expressionPattern.matches(advisedBeanName)) {
//        return FuzzyBoolean.YES;
//      }
//      if (beanFactory != null) {
//        String[] aliases = beanFactory.getAliases(advisedBeanName);
//        for (int i = 0; i < aliases.length; i++) {
//          if (this.expressionPattern.matches(aliases[i])) {
//            return FuzzyBoolean.YES;
//          }
//        }
//      }
      return FuzzyBoolean.NO;
    }
   
    private ClassMethodMatcher getMatcherClass(){
      try {
        Class<ClassMethodMatcher> classz = (Class<ClassMethodMatcher>) Class.forName(matchClassName);
        try {
          ClassMethodMatcher matcher = classz.getConstructor(null).newInstance(null);
          return matcher;
        } catch (Exception e) {
          throw new CheckedExceptionWrapper(e);
        }
      } catch (ClassNotFoundException e) {
        throw new CheckedExceptionWrapper(e);
      }
    }
  }


  public ClassFilter getClassFilter() {
    return this;
  }


  public com.gwtent.aop.MethodMatcher getMethodMatcher() {
    return this;
  }


}
TOP

Related Classes of com.gwtent.aop.matcher.AspectJExpress

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.