content: package com.alibaba.jvm.sandbox.core.util.matcher;
  
  import com.alibaba.jvm.sandbox.api.filter.AccessFlags;
  import com.alibaba.jvm.sandbox.api.filter.ExtFilter;
  import com.alibaba.jvm.sandbox.api.filter.ExtFilter.ExtFilterFactory;
  import com.alibaba.jvm.sandbox.api.filter.ExtFilterImplByV140;
  import com.alibaba.jvm.sandbox.api.filter.Filter;
  import com.alibaba.jvm.sandbox.api.listener.ext.EventWatchCondition;
  import com.alibaba.jvm.sandbox.core.util.matcher.structure.*;
  import org.apache.commons.io.IOUtils;
  import org.apache.commons.lang3.ArrayUtils;
  
  import java.io.InputStream;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.List;
  
  import static com.alibaba.jvm.sandbox.api.filter.AccessFlags.*;
  import static com.alibaba.jvm.sandbox.core.util.SandboxStringUtils.toInternalClassName;
  
  /**
   * 过滤器实现的匹配器
   *
   * @author luanjia@taobao.com
   */
  public class ExtFilterMatcher implements Matcher {
  
      private final ExtFilter extFilter;
  
      public ExtFilterMatcher(final ExtFilter extFilter) {
          this.extFilter = extFilter;
      }
  
      // 获取需要匹配的类结构
      // 如果要匹配子类就需要将这个类的所有家族成员找出
      private Collection<ClassStructure> getWaitingMatchClassStructures(final ClassStructure classStructure) {
          final Collection<ClassStructure> waitingMatchClassStructures = new ArrayList<>();
          waitingMatchClassStructures.add(classStructure);
          if (extFilter.isIncludeSubClasses()) {
              waitingMatchClassStructures.addAll(classStructure.getFamilyTypeClassStructures());
          }
          return waitingMatchClassStructures;
      }
  
      private String[] toJavaClassNameArray(final Collection<ClassStructure> classStructures) {
          if (null == classStructures) {
              return null;
          }
          final List<String> javaClassNames = new ArrayList<>();
          for (final ClassStructure classStructure : classStructures) {
              javaClassNames.add(classStructure.getJavaClassName());
          }
          return javaClassNames.toArray(new String[0]);
      }
  
      private boolean matchingClassStructure(ClassStructure classStructure) {
          for (final ClassStructure wmCs : getWaitingMatchClassStructures(classStructure)) {
  
              // #292 性能优化
              final boolean isHasInterfaceTypes, isHasAnnotationTypes;
              if (extFilter instanceof ExtFilterImplByV140) {
                  final ExtFilterImplByV140 v140 = (ExtFilterImplByV140) extFilter;
                  isHasInterfaceTypes = v140.isHasInterfaceTypes();
                  isHasAnnotationTypes = v140.isHasAnnotationTypes();
              } else {
                  isHasInterfaceTypes = isHasAnnotationTypes = true;
              }
  
              // 匹配类结构
              if (extFilter.doClassFilter(
                      toFilterAccess(wmCs.getAccess()),
                      wmCs.getJavaClassName(),
                      null == wmCs.getSuperClassStructure()
                              ? null
                              : wmCs.getSuperClassStructure().getJavaClassName(),
                      toJavaClassNameArray(
                              isHasInterfaceTypes
                                      ? wmCs.getFamilyInterfaceClassStructures()
                                      : Collections.emptySet()
                      ),
                      toJavaClassNameArray(
                              isHasAnnotationTypes
                                      ? wmCs.getFamilyAnnotationTypeClassStructures()
                                      : Collections.emptySet()
                      )
              )) {
                  return true;
              }
          }
          return false;
      }
  
      @Override
      public MatchingResult matching(final ClassStructure classStructure) {
  
          try {
              return _matching(classStructure);
          } catch (NoClassDefFoundError error) {
  
              // 根据 #203 ClassStructureImplByJDK会存在类加载异步的问题
              // 所以这里对JDK实现的ClassStructure抛出NoClassDefFoundError的时候做一个兼容
              // 转换为ASM实现然后进行match
              if (classStructure instanceof ClassStructureImplByJDK
                      && classStructure.getClassLoader() != null) {
                  final String javaClassResourceName = toInternalClassName(classStructure.getJavaClassName()).concat(".class");
                  InputStream is = null;
                  try {
                      is = classStructure.getClassLoader().getResourceAsStream(javaClassResourceName);
                      _matching(ClassStructureFactory.createClassStructure(is, classStructure.getClassLoader()));
                  } finally {
                      IOUtils.closeQuietly(is);
                  }
              }
  
              // 其他情况就直接抛出error
              throw error;
          }
  
      }
  
      private MatchingResult _matching(final ClassStructure classStructure) {
          final MatchingResult result = new MatchingResult();
          // 如果不开启加载Bootstrap的类，遇到就过滤掉
          if (!extFilter.isIncludeBootstrap()
                  && classStructure.getClassLoader() == null) {
              return result;
          }
  
          // 匹配ClassStructure
          if (!matchingClassStructure(classStructure)) {
              return result;
          }
  
          final boolean isBehaviorHasWithParameterTypes, isBehaviorHasExceptionTypes, isBehaviorHasAnnotationTypes;
          if(extFilter instanceof ExtFilterImplByV140) {
              final ExtFilterImplByV140 v140 = (ExtFilterImplByV140)extFilter;
              isBehaviorHasWithParameterTypes = v140.isBehaviorHasWithParameterTypes();
              isBehaviorHasExceptionTypes = v140.isBehaviorHasExceptionTypes();
              isBehaviorHasAnnotationTypes = v140.isBehaviorHasAnnotationTypes();
          } else {
              isBehaviorHasWithParameterTypes = true;
              isBehaviorHasExceptionTypes = true;
              isBehaviorHasAnnotationTypes = true;
          }
  
          // 匹配BehaviorStructure
          for (final BehaviorStructure behaviorStructure : classStructure.getBehaviorStructures()) {
  
              final String[] parameterTypeArrays = isBehaviorHasWithParameterTypes
                      ? toJavaClassNameArray(behaviorStructure.getParameterTypeClassStructures())
                      : new String[0];
  
              final String[] exceptionTypeArrays = isBehaviorHasExceptionTypes
                      ? toJavaClassNameArray(behaviorStructure.getExceptionTypeClassStructures())
                      : new String[0];
  
              final String[] annotationTypeArrays = isBehaviorHasAnnotationTypes
                      ? toJavaClassNameArray(behaviorStructure.getAnnotationTypeClassStructures())
                      : new String[0];
  
              if (extFilter.doMethodFilter(
                      toFilterAccess(behaviorStructure.getAccess()),
                      behaviorStructure.getName(),
                      parameterTypeArrays,
                      exceptionTypeArrays,
                      annotationTypeArrays
              )) {
                  result.getBehaviorStructures().add(behaviorStructure);
              }
          }
          return result;
      }
  
  
      /**
       * 转换为{@link AccessFlags}的Access体系
       *
       * @param access access flag
       * @return 部分兼容ASM的access flag
       */
      private static int toFilterAccess(final Access access) {
          int flag = 0;
          if (access.isPublic()) flag |= ACF_PUBLIC;
          if (access.isPrivate()) flag |= ACF_PRIVATE;
          if (access.isProtected()) flag |= ACF_PROTECTED;
          if (access.isStatic()) flag |= ACF_STATIC;
          if (access.isFinal()) flag |= ACF_FINAL;
          if (access.isInterface()) flag |= ACF_INTERFACE;
          if (access.isNative()) flag |= ACF_NATIVE;
          if (access.isAbstract()) flag |= ACF_ABSTRACT;
          if (access.isEnum()) flag |= ACF_ENUM;
          if (access.isAnnotation()) flag |= ACF_ANNOTATION;
          return flag;
      }
  
      /**
       * 兼容{@code sandbox-api:1.0.10}时
       * 在{@link EventWatchCondition#getOrFilterArray()}中将{@link Filter}直接暴露出来的问题，
       * 所以这里做一个兼容性的强制转换
       *
       * <ul>
       * <li>如果filterArray[index]是一个{@link ExtFilter}，则不需要再次转换</li>
       * <li>如果filterArray[index]是一个{@link Filter}，则需要进行{@link ExtFilterFactory#make(Filter)}的转换</li>
       * </ul>
       *
       * @param filterArray 过滤器数组
       * @return 兼容的Matcher
       */
      public static Matcher toOrGroupMatcher(final Filter[] filterArray) {
          final ExtFilter[] extFilterArray = new ExtFilter[filterArray.length];
          for (int index = 0; index < filterArray.length; index++) {
              extFilterArray[index] = ExtFilterFactory.make(filterArray[index]);
          }
          return toOrGroupMatcher(extFilterArray);
      }
  
      /**
       * 将{@link ExtFilter}数组转换为Or关系的Matcher
       *
       * @param extFilterArray 增强过滤器数组
       * @return Or关系Matcher
       */
      public static Matcher toOrGroupMatcher(final ExtFilter[] extFilterArray) {
          final Matcher[] matcherArray = new Matcher[ArrayUtils.getLength(extFilterArray)];
          for (int index = 0; index < matcherArray.length; index++) {
              matcherArray[index] = new ExtFilterMatcher(extFilterArray[index]);
          }
          return new GroupMatcher.Or(matcherArray);
      }
  
  }
  