001package net.gdface.codegen.thrift; 002 003import org.apache.commons.configuration2.Configuration; 004import org.slf4j.Logger; 005import org.slf4j.LoggerFactory; 006 007import com.facebook.swift.codec.metadata.PatternFilter; 008import com.google.common.base.Function; 009import com.google.common.base.Joiner; 010import com.google.common.base.Predicate; 011import com.google.common.collect.ImmutableMap; 012import com.google.common.collect.Maps; 013import com.google.common.collect.Sets; 014 015import net.gdface.annotation.DeriveMethod; 016 017import static com.google.common.base.Preconditions.*; 018import static net.gdface.utils.MiscellaneousUtils.*; 019 020import java.lang.reflect.Method; 021import java.util.ArrayList; 022import java.util.Arrays; 023import java.util.List; 024import java.util.Map; 025import java.util.Map.Entry; 026import java.util.Set; 027 028/** 029 * 根据配置文件提供的过滤参数对接口中的方法进行过滤 030 * @author guyadong 031 * 032 */ 033public class MethodFilter implements Predicate<Method>{ 034 private static final Logger logger = LoggerFactory.getLogger(MethodFilter.class); 035 private static final String SUFFIX_INCLUDE =".include"; 036 private static final String SUFFIX_EXCLUDE =".exclude"; 037 038 private final Configuration configuration = ThriftServiceDecoratorConfiguration.INSTANCE.getConfig(); 039 private Set<Method> includeMethods; 040 private Set<Method> excludeMethods; 041 public MethodFilter(Class<?> interfaceClass) { 042 checkArgument(interfaceClass != null,"interfaceClass is null"); 043 ImmutableMap<String, Method> methods = Maps.uniqueIndex(Arrays.asList(interfaceClass.getDeclaredMethods()), new Function<Method, String>() { 044 045 @Override 046 public String apply(Method input) { 047 StringBuffer buffer = new StringBuffer(input.getName()); 048 DeriveMethod dm = input.getAnnotation(DeriveMethod.class); 049 if(dm != null && dm.methodSuffix().length > 0){ 050 buffer.append('.').append(dm.methodSuffix()[0]); 051 } 052 return buffer.toString(); 053 } 054 }); 055 String includeKey = interfaceClass.getName() + SUFFIX_INCLUDE; 056 String excludeKey = interfaceClass.getName() + SUFFIX_EXCLUDE; 057 includeMethods = getMethodList(includeKey,interfaceClass,methods,false); 058 excludeMethods = getMethodList(excludeKey,interfaceClass,methods,true); 059 if(excludeMethods.isEmpty()){ 060 excludeMethods = getExcludeMethodList(interfaceClass,methods); 061 } 062 if(includeMethods.isEmpty()){ 063 includeMethods = getIncludeMethodList(interfaceClass,methods); 064 } 065 if(!includeMethods.isEmpty() && !excludeMethods.isEmpty()){ 066 logger.warn("{} and {} all defined, this first used preferentially",includeKey,excludeKey); 067 } 068 } 069 private List<Method> findMethod(String pattern,Map<String, Method> methods,boolean startsWithAsTrue){ 070 List<Method> found = new ArrayList<>(); 071 for(Entry<String, Method> entry:methods.entrySet()){ 072 String key = entry.getKey(); 073 String port = key; 074 if(key.indexOf(".") >= 0){ 075 port=Joiner.on("").join(key.split("\\.")); 076 } 077 if(PatternFilter.filter(pattern, port,startsWithAsTrue)){ 078 found.add(entry.getValue()); 079 } 080 } 081 return found; 082 } 083 private Set<Method> getMethodList(String key,Class<?> interfaceClass,Map<String, Method> methods,boolean startsWithAsTrue){ 084 Set<Method> sets = Sets.newHashSet(); 085 if(configuration.containsKey(key)){ 086 for(String name:elementsOf(configuration.getString(key))){ 087 List<Method> found = findMethod(name,methods,startsWithAsTrue); 088 if(found.isEmpty()){ 089 logger.warn("NOT FOUND Method named '{}' in {}",name,interfaceClass.getName()); 090 continue; 091 } 092 sets.addAll(found); 093 } 094 } 095 return sets; 096 } 097 private Set<Method> getExcludeMethodList(Class<?> interfaceClass,Map<String, Method> methods){ 098 Set<Method> sets = Sets.newHashSet(); 099 List<String> names = ThriftServiceDecoratorConfiguration.INSTANCE.getExcludeMethods().get(interfaceClass); 100 if(names != null){ 101 for(String name:names){ 102 List<Method> found = findMethod(name,methods,true); 103 if(found.isEmpty()){ 104 logger.warn("NOT FOUND Method named '{}' in {}",name,interfaceClass.getName()); 105 continue; 106 } 107 sets.addAll(found); 108 } 109 } 110 return sets; 111 } 112 private Set<Method> getIncludeMethodList(Class<?> interfaceClass,Map<String, Method> methods){ 113 Set<Method> sets = Sets.newHashSet(); 114 List<String> names = ThriftServiceDecoratorConfiguration.INSTANCE.getIncludeMethods().get(interfaceClass); 115 if(names != null){ 116 for(String name:names){ 117 List<Method> found = findMethod(name,methods,false); 118 if(found.isEmpty()){ 119 logger.warn("NOT FOUND Method named '{}' in {}",name,interfaceClass.getName()); 120 continue; 121 } 122 sets.addAll(found); 123 } 124 } 125 return sets; 126 } 127 @Override 128 public boolean apply(Method input) { 129 if(!includeMethods.isEmpty()){ 130 return includeMethods.contains(input); 131 } 132 if(!excludeMethods.isEmpty()){ 133 return !excludeMethods.contains(input); 134 } 135 return true; 136 } 137 138 139}