Skip to content

Instantly share code, notes, and snippets.

@monzou
Created April 1, 2011 02:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save monzou/897622 to your computer and use it in GitHub Desktop.
Save monzou/897622 to your computer and use it in GitHub Desktop.
package scripts;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import net.arnx.jsonic.JSON;
import net.arnx.jsonic.JSONException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
/**
* ClassJSONWriter
*
* @author monzou
*/
public class ClassJSONWriter {
public static void main(String[] args) throws IOException, ClassNotFoundException {
String dir = (String) args[0];
String[] packages = (String[]) ArrayUtils.subarray(args, 1, args.length);
System.out.println("output directory=" + dir);
System.out.println("target packages=" + StringUtils.join(packages, ", "));
new ClassJSONWriter(dir).write(dir, packages);
}
private static final String JSON_EXTENSION = "json";
private final JavaClassFinder finder;
ClassJSONWriter(String dir) {
finder = new JavaClassFinder();
}
void write(String dir, String... packages) throws IOException, ClassNotFoundException {
JSONFileWriter writer = new JSONFileWriter(dir);
writer.prepareDirectory();
for (String pkg : packages) {
for (Class<?> clazz : finder.findAll(pkg, true)) {
System.out.println(clazz.getName());
writer.write(clazz);
}
}
}
private static class JSONFileWriter {
private final ClassBeanConverter converter;
private File directory;
JSONFileWriter(String dir) {
converter = new ClassBeanConverter();
directory = new File(dir);
}
void write(Class<?> clazz) throws IOException {
ClassBean bean = converter.toBean(clazz);
String path = String.format("%s/%s.%s", directory.getPath(), bean.className, JSON_EXTENSION);
try {
FileOutputStream out = new FileOutputStream(new File(path));
JSON.encode(bean, out);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
boolean prepareDirectory() throws IOException {
if (directory.exists()) {
cleanDirectory();
return false;
} else {
return directory.mkdirs();
}
}
void cleanDirectory() throws IOException {
if (directory.exists()) {
FileUtils.cleanDirectory(directory);
}
}
}
private static class JavaClassFinder {
public List<Class<?>> findAll(String pkg, boolean recursive) throws IOException, ClassNotFoundException {
String regex = String.format(".*(%s.*)\\.class", pkg.replaceAll("\\.", "/"));
System.err.println(regex);
Pattern pattern = Pattern.compile(regex);
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
JavaFileManager fm = compiler.getStandardFileManager(new DiagnosticCollector<JavaFileObject>(), null, null);
Set<Kind> kinds = Sets.newHashSet(JavaFileObject.Kind.CLASS);
List<Class<?>> classes = Lists.newArrayList();
for (JavaFileObject f : fm.list(StandardLocation.CLASS_PATH, pkg, kinds, recursive)) {
String path = f.toUri().getPath();
if (isApplicable(path)) {
Matcher matcher = pattern.matcher(path);
if (matcher.matches()) {
classes.add(Class.forName(matcher.group(1).replaceAll("/", ".")));
}
}
}
return classes;
}
private boolean isApplicable(String path) {
if (path.contains("$") || path.contains("package-info") || path.contains("Test")) {
// Proxy, package-info, Test は除外
return false;
}
return true;
}
}
private static class ClassBeanConverter {
private static final Function<Class<?>, String> CLASS_NAME_RESOLVER = new Function<Class<?>, String>() {
/** {@inheritDoc} */
@Override
public String apply(Class<?> input) {
return input.getName();
}
};
public ClassBean toBean(Class<?> clazz) {
ClassBean bean = new ClassBean();
bean.className = clazz.getSimpleName();
bean.packageName = clazz.getPackage().getName();
bean.methods = Lists.newArrayList();
for (Method method : clazz.getDeclaredMethods()) {
if (ignoreMethod(method)) {
continue;
}
MethodBean mb = new MethodBean();
mb.methodName = method.getName();
mb.returnType = method.getReturnType().getName();
mb.argTypes = joinClassNames(method.getParameterTypes());
mb.throwables = joinClassNames(method.getExceptionTypes());
bean.methods.add(mb);
}
return bean;
}
private String joinClassNames(Class<?>[] classes) {
Joiner joiner = Joiner.on(", ");
return joiner.join(Collections2.transform(Lists.newArrayList(classes), CLASS_NAME_RESOLVER));
}
private boolean ignoreMethod(Method method) {
if (method.getDeclaringClass() == Object.class) {
return true;
}
return method.isSynthetic() || method.isBridge();
}
}
public static class ClassBean {
public String packageName;
public String className;
public List<MethodBean> methods;
}
public static class MethodBean {
public String methodName;
public String argTypes;
public String returnType;
public String throwables;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment