インターフェースのメソッドの仮引数名を取得する

いろいろと調べた結果、interfaceのclassファイルにはメソッドの仮引数名の情報は含まれていないようなので、結局、ソースをパースすることにした。
最初はJavaDoc用のライブラリを使おうとしたが、使い方がいまいちよくわからなかったので、自前でパーサを作成。
正規表現はあってるかな…


public class InterfaceParser {

private static Pattern method_pattern = Pattern.compile("(?:[a-z]+\\s+)*(?:[A-Za-z_$][A-Za-z_$0-9]*\\s*(?:\\[\\s*\\])*)\\s+([A-Za-z_$][A-Za-z_$0-9]*)\\s*\\*1;
}

public InterfaceParser(Class clazz, File srcfile) throws IOException {
this.clazz = clazz;
String src = read(srcfile);
Matcher m = method_pattern.matcher(src);

while (m.find()) {
String method = m.group(1);
String paramsdesc = m.group(2).trim();
add(method, paramsdesc);
}
}

public void add(String method, String paramsdesc) {
if (empty_pattern.matcher(paramsdesc).matches()) {
arguments.put("", new String[0]);
return;
}

String params = separator_pattern.split(paramsdesc, 2);
String
types = new String[params.length];
String names = new String[params.length];

for (int i = 0; i < params.length; i++) {
String pair = space_pattern.split(params[i], 2);
types[i] = pair[0];
names[i] = pair[1];
}

arguments.put(join(types, ", "), names);
}

public MethodInfo getMethodInfos() {
Method
methods = clazz.getMethods();
MethodInfo infos = new MethodInfo[methods.length];

for (int i = 0; i < methods.length; i++)
infos[i] = getMethodInfo(methods[i]);

return infos;
}

private MethodInfo getMethodInfo(Method method) {
Class types = method.getParameterTypes();
String shortnames = new String[types.length];

for (int i = 0; i < types.length; i++)
shortnames[i] = getShortClassName(types[i]);

String names = (String) arguments.get(join(shortnames, ", "));
return new MethodInfo(method, names);
}

/////////////////////////////////////////////////////////////////

private String read(File file) throws IOException {
FileReader reader = new FileReader(file);
StringWriter writer = new StringWriter();

char buf = new char[1024];
int len = 0;

while ( (len = reader.read(buf) ) > 0)
writer.write(buf, 0, len);

return writer.toString();
}

private String join(String ary, String sep) {
if (ary.length < 1)
return "";

StringBuffer buf = new StringBuffer(ary[0]);

for (int i = 1; i < ary.length; i++) {
buf.append(sep);
buf.append(ary[i]);
}

return buf.toString();
}

private String getShortClassName(Class clazz) {
String fqcn = clazz.isArray() ? clazz.getComponentType().getName() : clazz.getName();
int pos = fqcn.lastIndexOf(".");
String shortname = (pos < 0) ? fqcn : fqcn.substring(pos + 1);

if (!clazz.isArray())
return shortname;

StringBuffer aryshortname = new StringBuffer(shortname);
int dim = clazz.getName().lastIndexOf("[") + 1;

for (int i = 0; i < dim; i++)
aryshortname.append("");

return aryshortname.toString();
}

}



public class MethodInfo {

private Method method = null;

private String formal_arguments = null;

public MethodInfo(Method method, String formal_arguments) {
this.method = method;
this.formal_arguments = formal_arguments;
}

public Method getMethod() {
return method;
}

public String[] getFormalArguments() {
return formal_arguments;
}

}

*1:[^)]*)\\)", Pattern.MULTILINE); private static Pattern empty_pattern = Pattern.compile("\\s*", Pattern.MULTILINE); private static Pattern separator_pattern = Pattern.compile("\\s*,\\s*", Pattern.MULTILINE); private static Pattern space_pattern = Pattern.compile("\\s+", Pattern.MULTILINE); private Class clazz = null; private Map arguments = new HashMap(); public InterfaceParser(Class clazz, String srcpath) throws IOException { this(clazz, new File(srcpath