package cn.org.rapid_framework.generator.util.paranamer; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import cn.org.rapid_framework.generator.util.IOHelper; import cn.org.rapid_framework.generator.util.StringHelper; /** * get parameter names from java source file * @author badqiu */ public class JavaSourceParanamer implements Paranamer{ private ClassLoader classLoader; public JavaSourceParanamer(ClassLoader classLoader) { if(classLoader == null) throw new IllegalArgumentException("'classLoader' must be not null"); this.classLoader = classLoader; } public String[] lookupParameterNames(AccessibleObject methodOrConstructor) { return lookupParameterNames(methodOrConstructor,true); } @SuppressWarnings("unchecked") public String[] lookupParameterNames(AccessibleObject methodOrConstructor,boolean throwExceptionIfMissing) { try { JavaSourceFileMethodParametersParser parser = new JavaSourceFileMethodParametersParser(); String javaSource = null; if(methodOrConstructor instanceof Method) { Method m = (Method)methodOrConstructor; javaSource = m.getDeclaringClass().getName().replace('.', '/')+".java"; }else if(methodOrConstructor instanceof Constructor) { Constructor c = (Constructor)methodOrConstructor; javaSource = c.getDeclaringClass().getName().replace('.', '/')+".java"; }else { throw new IllegalArgumentException("unknow AccessibleObject"+methodOrConstructor+",must be Method or Constructor"); } InputStream javaSourceInputStream = classLoader.getResourceAsStream(javaSource); try { if(javaSourceInputStream != null) { return parser.parseJavaFileForParamNames(methodOrConstructor, IOHelper.toString(javaSourceInputStream)); } return Paranamer.EMPTY_NAMES; }finally { if(javaSourceInputStream != null) javaSourceInputStream.close(); } }catch(IOException e) { if(throwExceptionIfMissing) { throw new RuntimeException("IOException while reading javasource,method:"+methodOrConstructor,e); }else { return Paranamer.EMPTY_NAMES; } } } public static class JavaSourceFileMethodParametersParser { public String[] parseJavaFileForParamNames(Constructor<?> constructor,String content) { return parseJavaFileForParamNames(content,constructor.getName(),constructor.getParameterTypes()); } public String[] parseJavaFileForParamNames(Method method,String content) { return parseJavaFileForParamNames(content, method.getName(), method.getParameterTypes()); } public String[] parseJavaFileForParamNames(AccessibleObject methodOrConstructor,String content) { if(methodOrConstructor instanceof Method) { return parseJavaFileForParamNames((Method)methodOrConstructor,content); }else if(methodOrConstructor instanceof Constructor) { return parseJavaFileForParamNames((Constructor)methodOrConstructor,content); }else { throw new IllegalArgumentException("unknow AccessibleObject"+methodOrConstructor+",must be Method or Constructor"); } } private String[] parseJavaFileForParamNames(String content, String name, Class<?>[] parameterTypes) { Pattern methodPattern = Pattern.compile("(?s)"+name+"\\s*\\("+getParamsPattern(parameterTypes)+"\\)\\s*\\{"); Matcher m = methodPattern.matcher(content); List<String> paramNames = new ArrayList<String>(); while(m.find()) { for(int i = 1; i <= parameterTypes.length; i++) { paramNames.add(m.group(i)); } return (String[])paramNames.toArray(new String[0]); } return null; } private String getParamsPattern(Class<?>[] parameterTypes) { List paramPatterns = new ArrayList(); for(int i = 0; i < parameterTypes.length; i++ ) { Class type = parameterTypes[i]; String paramPattern = ".*"+type.getSimpleName()+".*\\s+(\\w+).*"; paramPatterns.add(paramPattern); } return StringHelper.join(paramPatterns, ","); } } }